• Day15:网络编程-Socket(UDP、TCP)


    Java语言是一门Internet语言,遇过不可以从Internet获取数据,Java就是死的,因此网络编程就是描述Java怎么从Internet获取数据!

    网络要素:
    IP: 地址<--解析-->主机名  InetAddress  getByName(hostname); getHostAddress  getHostName
    端口:0-65535  
    协议:
    1、TCP(面向连接,可靠,效率稍低。)---客户端:Socket  服务端ServerSocket  
    2、UDP(面向无连接,不可靠,速度快)---发送端,接收端。DatagramSocket  ----  DatagramPacket(数据包)

    在网络编程中,最重要部分非Socket莫属了,无论大小面试,对非常钟爱与Socket,因为Socket是网络通信的基础,是网络通信的最重要的工具

    先用Socket实现UDP通信

    /*
     * 需求:建立UDP的发送端
     * 思路:
    * 1、建立可以实现UDP传输的socket服务
    * 2、明确具体发送的数据
     * 3、通过socket服务将具体数据发送出去
    * 4、关闭服务  
    */
    //1、创建UDP服务
      try {
        DatagramSocket ds = new DatagramSocket();
        //2、明确数据
        String str = "注意啦,UDP要来啦!";
        //3、发送数据,将数据封装到数据包中
        byte[] buf = str.getBytes();
        DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.137.1"), 9090); 
        ds.send(dp);
        //4、关闭服务
        ds.close();
        } catch (SocketException e) {
            // TODO Auto-generated catch block
            System.out.println("UDP服务发送端启动失败");
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            System.out.println("数据包发送失败");
            e.printStackTrace();
        }
    /*
     * 需求:建立UDP接收端
     * 思路:
    * 1、创建socket服务,明确接受数据的端口
    * 2、接受数据包
    * 3、将接收到的数据包中的数据取出来,取出的数据包括IP、data、port
    * 4、关闭服务
    */
        try {
        DatagramSocket ds = new DatagramSocket(9090);
        System.out.println("接收端启动成功!");
        //3、接收数据包
        byte[] buf = new byte[1000];
        DatagramPacket dp = new DatagramPacket(buf, buf.length);        
        ds.receive(dp);//阻塞式方法,使得Receive类开启时在等待状态,直到接收到数据才结束
        //解析数据
        StringBuilder sb = new StringBuilder();
        sb.append("发送数据的IP为:"+dp.getAddress().getHostAddress()+"
    ");
        sb.append("接收到的数据为:"+new String(dp.getData(),0,dp.getLength())+"
    ");
        sb.append("接收数据端口为:"+dp.getPort());
        System.out.println(sb.toString());
        //4、关闭服务
        ds.close();
        } catch (SocketException e) {
            // TODO Auto-generated catch block
            System.out.println("接收端启动失败!");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            System.out.println("数据包接收失败!");
        }
    //一个利用UDP协议写的一个半实现的聊天室

    public
    class UDPChatRoom { /** * @param args * @throws SocketException */ public static void main(String[] args) throws SocketException { // TODO Auto-generated method stub /* * 需求:通过UDP协议完成一个聊天室程序(一个负责发送数据,另外一个负责接收数据,两个同时进行) */ //创建socket服务。 DatagramSocket send = new DatagramSocket(10086); DatagramSocket rece = new DatagramSocket(10010); new Thread(new Send(send)).start(); new Thread(new Receive(rece)).start(); } } // 负责发送的任务,通过UDPsocket发送。 class Send implements Runnable{ //建立数据包 private DatagramSocket ds; public Send(DatagramSocket ds){ super(); this.ds = ds; } @Override public void run() { // TODO Auto-generated method stub //1、建立可以实现UDP传输的socket服务 //2读取数据 BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); String line = null; try { while((line = bufr.readLine())!=null){ if("over".equals(line)){ System.out.println(ds.getLocalSocketAddress()+":"+".....发送者离开聊天室"); } byte[] buf = line.getBytes(); DatagramPacket dp = new DatagramPacket(buf, buf.length,InetAddress.getByName("192.168.137.1"),10010); //3发送数据 ds.send(dp); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } // 负责接收的任务 class Receive implements Runnable{ //建立数据包 private DatagramSocket ds; public Receive(DatagramSocket ds){ super(); this.ds = ds; } @Override public void run() { // TODO Auto-generated method stub while (true) { // 1,因为接收的数据最终都会存储到数据包中。而数据包中必须有字节数组。 byte[] buf = new byte[1024]; // 2,创建数据包对象。 DatagramPacket dp = new DatagramPacket(buf, buf.length); // 3,将收到的数据存储到数据包中。 try { ds.receive(dp); } catch (IOException e) { e.printStackTrace(); } // 4,获取数据。 String ip = dp.getAddress().getHostAddress(); String data = new String(dp.getData(), 0, dp.getLength()); System.out.println(ip + ":" + data); if("over".equals(data)){ System.out.println(ip+".....接受者离开聊天室"); } } } }

    再用Socket实现TCP通信

    /*
             * 需求:创建TCP服务端
             * 思路:
             * 1、创建Socket服务器端服务,服务端为了能让客户端连接上,必须提供端口并监听一个端口
             * 2、获取客户端对象,通过客户端的Socket流和对应的客户端进行通信
             * 3、获取客户端的Socket流的读取流
             * 4、读取数据并显示在服务器端
             * 5、关闭资源
             */
            //1、创建服务器端对象
            ServerSocket ss = new ServerSocket(10000);
            System.out.println("Server is Opening!");
            //2、获取客户端对象
            Socket s= ss.accept();
            String ip = s.getInetAddress().getHostAddress();
            //3、通过客户端对象获取Socket流的读取
            InputStream in = s.getInputStream();
            
            byte[] buf = new byte[1024];
            int len = in.read(buf);
            String str = new String(buf,0,len);
            
            System.out.println(ip+":"+str);
            
            s.close();
            ss.close();
    /*
             * 需求:TCP客户端的建立
             * 思路:
             * 1、建立TCP客户端服务
             *     1.1因为是面向连接,必须要有连接才可以实现通信
             *     1.2在创建客户端的同时,就必须明确目的地址和端口
             * 2、一旦连接建立,就有了传输数据的通道,就可以在通道中进行数据传输,数据的传输通过Socket-IO流实现
             * 3、只要获取Socket-IO流中的写动作就可以进行发送数据到服务端
             * 4、释放资源
             */
            //1、创建客户端对象。明确目的地址和端口
            Socket s = new Socket("192.168.137.1",10000);
            System.out.println("Client is opening!");
            //2、获取Socket流中的输出流,将数据发送到服务端
            OutputStream os = s.getOutputStream();
            //3、通过输出流写数据
            os.write("注意啦,TCP要来啦!".getBytes());
            //4、释放资源
            s.close();

    要实现高级一点的东西了,要利用TCP设计一个半实现的聊天工具

    /*
             * 服务端收到客户端的数据并反馈数据给客户端。应答。
             */
            //1,创建服务端socket对象。
            ServerSocket ss = new ServerSocket(10004);
            System.out.println("ChatServer is Opening......");
            
            //2,获取客户端对象。
            Socket s = ss.accept();
            String ip = s.getInetAddress().getHostAddress();
            System.out.println(ip+".....connected");
            
            //3, 获取socket读取流。
            InputStream in = s.getInputStream();    
            byte[] buf = new byte[1024];
            int len = in.read(buf);
            String str = new String(buf,0,len);
            System.out.println(str);
                
            //4,给客户端反馈数据。socket输出流。
            OutputStream out = s.getOutputStream();
            out.write("哦了,我知道你来了".getBytes());
            
            //5、释放资源
            s.close();
            ss.close();
    //需求:客户端发送数据给服务端,并读取服务端反馈的数据。
            System.out.println("ChatClient is Opening.....");
            //1,创建socket客户端。
            Socket s = new Socket("192.168.137.1",10004);
            
            //2,获取socket输出流。写数据。
            OutputStream out = s.getOutputStream();
            out.write("服务端,我来了.".getBytes());
            
            //3,获取socket的读取流。读取服务端发回的数据。
            InputStream in = s.getInputStream();
            byte[] buf = new byte[1024];
            int len = in.read(buf);
            String str = new String(buf,0,len);
            System.out.println(str);
            
            //4、释放资源
            s.close();    

    再高级一点,利用TCP协议进行传送文件了(包括图片、文本)

        /*
             * 上传文本的客户端。读取本地文本数据,发送给服务端,服务端接收完毕后,回馈"上传成功"字样。
             */
            //客户端socket
            Socket s = new Socket("192.168.137.1",10005);
            System.out.println("上传文本客户端启动......");
    
            //1,确定数据源。本地文件文件
            BufferedReader bufr = new BufferedReader(new FileReader("client.txt"));
    
            //2,确定目的IP和Socket-IO输出流
            PrintWriter out = new PrintWriter(s.getOutputStream(),true);
    
            String line = null;
            while((line=bufr.readLine())!=null){
                out.println(line);
            }
    
            //使用socket的禁用输出流方法来停止向服务端发送数据。
            s.shutdownOutput();
    
            //3,通过socket读取流获取服务端返回的数据。
            BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
            String lineIn = bufIn.readLine();//阻塞式。
            System.out.println(lineIn);
    
            //4,释放资源
            bufr.close();
            s.close();
    /*
             * 上传文本的服务端。接收文本数据,并存储到文件中,服务端接收完毕后,回馈"上传成功"字样。
             */
            //1,服务端对象。
            ServerSocket ss = new ServerSocket(10005);
            System.out.println("上传文本服务器端启动.......");
            
            //2,获取客户端。
            Socket s = ss.accept();
            String ip = s.getInetAddress().getHostAddress();
            System.out.println(ip+".....connected");
            
            //3,获取读取流。确定源,网络socket。
            BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
            
            //4,确定目的文件。
            PrintWriter pw = new PrintWriter(new FileWriter("server.txt"),true);
            
            //5,频繁读写。
            String line = null;
            while((line=bufIn.readLine())!=null){
                pw.println(line);
            }
            
            //6,给客户端返回信息。
            PrintWriter out = new PrintWriter(s.getOutputStream(),true);
            out.println("上传成功");
            
            //7、释放资源
            pw.close();
            s.close();
            ss.close();
    TCP的传输、上传、问题:两端等待的情况。说明有阻塞式方法。没有读取到结束标记。shutdown.
    
    web原理:并发访问,Server端:将来访的客户端都封装到了一个单独线程中。
                ServerSocket server  = new ServerSocket(10000);
                while(true)
                {
                    Socket s = server.accept();
                    new Thread(new Task(s)).start();
                }
  • 相关阅读:
    关于分区索引对齐
    SQLSERVER 分区表实战
    鱼骨图实践
    Python之路-python(面向对象一)
    Python之路-python(常用模块学习)
    Python之路-python(装饰器、生成器、迭代器、Json & pickle 数据序列化、软件目录结构规范)
    Python之路-python(set集合、文本操作、字符编码 )
    Python之路-python数据类型(列表、字典、字符串、元祖)操作
    Python之路-python环境安装和简单的语法使用
    javascript中with语句应用
  • 原文地址:https://www.cnblogs.com/vijay/p/3508071.html
Copyright © 2020-2023  润新知