• UDP协议


    背景

    进行网络编程,就需要传输层为应用层提供的api,称为socket api,其中传输层提供了两种协议,TCP和UDP,其所对应的socket api也是不同的,下面介绍的是UDP协议

    1.特点

    1.无连接(就像发微信、QQ一样无需对方回应,建立连接,消息也能发过去,而相对应的有连接则是像电话这样的,对方需要接电话,建立连接才能通信)
    2.不可靠传输(不知道对方有无收到消息,就像微信一样,对方有没有看见自己的消息是不知道的)
    3.面向数据报(以数据报为传输的基本单位)
    4.全双工(支持双向通信,可以在A给B通信的同时,B给A通信)

    2.核心类

    UDP的socket api提供的两大核心类分别为DatagramSocket类和DatagramPacket类
    1.DatagramSocket 叫作socket类,本质上是一个文件,在系统中,还有一种特殊的socket文件,对应于网卡设备,进行网络通信,就需要打开一个内核中的socket文件,可以构造DatagramSocket对象来打开这个文件
    2.DatagramPacket类,表示一个UDP数据报,传输数据,就是以DatagramPacket为基本单位
    3.还有一个重要的类InetSocketAddress,是用来创建Socket地址,包含IP地址和端口号。

    3.回显服务器的实现

    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.SocketException;
    import java.nio.charset.StandardCharsets;
    
    
    public class UdpEchoServer {
        //要创建UDP服务器,需要先打开一个socket文件
        private DatagramSocket socket = null;
        public UdpEchoServer(int port) throws SocketException {
            socket = new DatagramSocket(port);//绑定一个端口,将进程和端口号关联起来,程序如果要进行网络通信就需要一个端口号,端口号相当于网络上区分进程的身份标识符,端口号范围是0到65535
        }
        //启动服务器
        public void start() throws IOException {
            System.out.println("服务器启动");
            while(true){
                //1.读取客户端发来的请求
                DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);//分配了一段长度为4096的缓冲区(内存空间)
                socket.receive(requestPacket);//若客户端没发请求,receive就会阻塞等待,直到有请求,才会读取数据并且返回到输出型参数
                //2.对请求进行解析,把DatagramPacket(本质上是字节数组)转成一个String
                String request = new String(requestPacket.getData(),0,requestPacket.getLength());//将缓冲区中的字节数组取出来,转成字符串
               //3.根据请求处理响应
                String response = process(request);
                //4.把响应构造成DatagramPacket对象,用字符串里面的字节数组来构造内容,指定长度,还要将响应返回给客户端,getSocketAddress()是用了requestPacket存储的客户端的IP地址和端口号
                DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());
                //5.把这个DatagramPacket对象返回给客户端
                socket.send(responsePacket);
                System.out.println("客户端IP"+requestPacket.getAddress().toString()+"端口号"+requestPacket.getPort()+"请求"+request+"响应"+response);
            }
        }
    //通过这个方法,实现根据请求处理响应,根据自己的实际情况来编写代码,此处是回显服务器,发来什么返回什么。
        private String process(String request) {
            return request;
        }
    //启动服务器
        public static void main(String[] args) throws IOException {
            UdpEchoServer udpEchoServer = new UdpEchoServer(6888);//端口号一般不能取1024以下的端口,是系统保留的端口,特殊端口。一般取1024到65535
            udpEchoServer.start();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    4.客户端的实现

    import java.awt.*;
    import java.io.IOException;
    import java.net.*;
    import java.nio.charset.StandardCharsets;
    import java.util.Scanner;
    
    public class UdpEchoClient {
        private DatagramSocket socket = null;
    
        public UdpEchoClient() throws SocketException {
            //服务器得有固定端口客户端才好访问,客户端程序安装在用户电脑上,用户电脑上的端口号是不可控的,若指定端口号很有可能会重复
            socket = new DatagramSocket();//客户端端口号一般是由操作系统自动分配
    
        }
    
        public  void start() throws IOException {
            Scanner scanner = new Scanner(System.in);
    
            while (true) {
                //1.让客户端从控制台读取一个数据
                String request = scanner.next();
                //2.把这个请求发送给服务器,构造DatagramPacket,需要包含请求的数据内容和服务器的IP地址和端口号,127.0.0.1是环回IP,表示当前主机。
                DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length, InetAddress.getByName("127.0.0.1"),6888);
                //3.把数据发送给服务器
                socket.send(requestPacket);
                //4.从服务器读取响应数据
                DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);
                socket.receive(responsePacket);
                //5.转换响应的数据变成字符串
                String response = new String(responsePacket.getData(),0,responsePacket.getLength());
                System.out.println("request  "+request+ "   response  "+response);
            }
    
        }
    
        public static void main(String[] args) throws IOException {
            UdpEchoClient udpEchoClient = new UdpEchoClient();
            udpEchoClient.start();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    在这里插入图片描述
    在这里插入图片描述
    把这个√上就可以同时启动多个客户端。

    4. close方法

    上述构造了一个DatagramSocket对象,相当于打开了一个特殊文件,但没有关闭文件是因为socket对象生命周期是伴随整个进程的,而这个进程是始终没有结束的,故不能提前关闭socket对象,而当进程结束的时候,对应的PCB也就没有了,文件描述符也没有了,也就相当于关闭了文件。

  • 相关阅读:
    用go封装一下临时token
    常用的dos网络命令总结
    DeconvNet--学习笔记
    laravel框架 - 安装初步使用学习 composer安装
    量化分析革新金融服务软件的三种方式
    如何从任何苹果、Windows或安卓设备访问iCloud照片
    c++征途 --- 指针
    什么蓝牙耳机听歌好?听歌音质好的蓝牙耳机推荐
    IP组播基础
    基于go-micro微服务的实战-Gateway网关层的限流降级(八)
  • 原文地址:https://blog.csdn.net/zjychl/article/details/126839206