UDP Socket

前言

UDP是一种不可靠传输 不保证消息的可靠传递,因此有时被称为不可靠的数据报协议

在Java中UDP涉及两个类DatagramSocket 与DatagramPacket

要想理解UDP Socket编程必须要清楚上述两个 类的作用

DatagramSocket 与DatagramPacket

DatagramSocket 用于创建发送或接收数据报包的套接字(用于发送和接收消息)

DatagramPacket 用于表示数据报包本身 (属于是构造消息)

我们 以简单的回响服务器客户端为例

1.UdpEchoServer(服务端)

服务端的构造需要指定端口 这个被指定的端口就是 服务端的监控端口 用于监控是否有客户端请求

服务端的角色是被动连接,只需要在端口上等着 就像一个店铺只需要固定门牌号(端口),不需要知道客人是谁,客人自然会找上门来

1.首先作为服务端要有接收和 发送信息的能力 声明属性DatagramSocket

2.构造服务端 声明端口 以此端口来创建DatagramSocket 实例

3.设置一个request数据包 利用receive方法来获取到客户端发送的消息 为什么说request是输出型参数 ,大家可以类似理解为最初request是空的 但是经过receive函数 request被赋予了值,这个值就是客户端发送的,物理介质就是网卡

4.解析请求内容 获取0到实际数据长度内容

5.根据请求计算响应 此处因为我们是 简单的回响服务器 此处省略处理

6.构造响应,响应以 字节形式 传输,长度,但需注意udp本身不存储双方信息 所以我们需要在数据包中加入发出请求的 目标Ip和目标端口

7.将构造好的响应通过send发送给 客户端

2.UdpEchoClient(客户端)

客户端 的角色是要主动去找 所以必须要知道 自己要去哪 IP 和 端口

就像你去吃饭必须知道餐厅的地址和门牌号,否则你根本不知道该去哪

1.DatagramSocket不指定端口 是因为它不需要去指定标识 在运行时操作 系统会为他自动分配一个临时 端口 所以我们不建议在DatagramSocket中指定端口 由于服务端端口时是它 的标识和门牌号 所以它必须去创建门牌实例 此处则不需要

2.构造DatagramPacket 数据包去发送给服务端 数据包中要加入消息的字节化数据 和目标Ip 和目标 端口 表明这是你信息要发送的位置

3.仍然是输出型参数 先 声明一个空的 response 在receive中再从网卡中读取到服务端 的响应 然后赋给response

4.解析响应有效字节数据

疑问点:

为什么服务端要指定DatagramSocket端口?

因为 服务端要设定一个 门牌号 这样客户端发送信息时,就可以用来监控请求 而客户端操作系统会自动为客户端的DatagramSocket分配端口号,因为没有必要去指定端口 发送信息时客户端的IP 和端口会被包装在数据包中,服务端就直接可以通过数据包解析出 客户端的Ip和端口号

具体的通信过程?

服务端 有一个端口号相当于门牌 表明位置

客户端 通过你手动代码去提供 服务端 的IP 和端口, 客户端本身IP和端口号操作系统会自动分配端口 发送信息时将自身IP和 端口包装在数据包中

服务端收到客户端 的信息后 ,就通过数据包中的ip和端口 将响应发送给客户端

源代码:

UdpEchoServer

java 复制代码
public class UdpEchoServer {

    private DatagramSocket datagramSocket;

    public UdpEchoServer(int port) throws SocketException {
        //指定一个端口号来使用 此端口用于监控请求
        this.datagramSocket=new DatagramSocket(port);
    }
    public void start() throws IOException {
        //启动服务器
        System.out.println("服务器启动");
        while(true) {
            //1.获取客户端请求并解析
            //先设置一个空的request
            DatagramPacket request=new DatagramPacket(new byte[4096],4096);
            //从网卡中获取 到request的内容 输出到request中(输出型参数)
            datagramSocket.receive(request);
            //解析请求 获取到请求内容
            String words=new  String(request.getData(),0,request.getLength());
            //2.根据请求计算响应
            String key=process(words);
            //3.返回响应给客户端
            DatagramPacket response=new DatagramPacket(key.getBytes(),0,
                    key.getBytes().length,request.getAddress(), request.getPort());
            datagramSocket.send(response);
           //打印数据报发送成功
            System.out.println("key 成功发送"+key);
        }
    }

    private String process(String words) {
        return words;
    }

    public static void main(String[] args) throws IOException {
        UdpEchoServer server=new UdpEchoServer(8888);
        server.start();
    }
}

UdpEchoClient

java 复制代码
public class UdpEchoClient {
     private int port;
     private String serverIp;
     private DatagramSocket datagramSocket;
     public UdpEchoClient(int port,String  server) throws SocketException {
         this.port=port;
         this.serverIp=server;
         this.datagramSocket=new DatagramSocket();
     }
     public void start() throws IOException {
         //客户端 服务启动
         System.out.println("客户端服务启动");
         while(true){
             Scanner  sc=new Scanner(System.in);
             System.out.println("请输入:");
             String key=sc.next();
             //1.构造DatagramPocket数据报发送消息
             DatagramPacket  request=new DatagramPacket(key.getBytes(),0,
                     key.getBytes().length,InetAddress.getByName(serverIp),port);
             datagramSocket.send(request);
             //接收服务器的响应
             DatagramPacket  response=new DatagramPacket(new byte[4096],4096);
             datagramSocket.receive(response);
             //解析响应内容
             String words=new String(response.getData(),0,response.getLength());
             System.out.println(words);
             System.out.println("解析成功");
         }
     }

    public static void main(String[] args) throws IOException {
        UdpEchoClient client=new UdpEchoClient(8888,"127.0.0.1");
        client.start();
    }

}
相关推荐
Godspeed Zhao8 小时前
现代智能汽车中的无线技术106——ETC(0)
网络·人工智能·汽车
枷锁—sha9 小时前
【pwn系列】Pwndbg 汇编调试实操教程
网络·汇编·笔记·安全·网络安全
盟接之桥10 小时前
盟接之桥EDI软件:API数据采集模块深度解析,打造企业数据协同新引擎
java·运维·服务器·网络·数据库·人工智能·制造
2501_9071368210 小时前
离线工具箱 内含53个小工具
linux·服务器·网络
时空潮汐10 小时前
神卓N600 NAS身份核验功能深度解析
linux·运维·网络·神卓nas·神卓n600 pro·家庭轻nas
一路往蓝-Anbo11 小时前
第 7 章:内存地图 (Memory Map) 深度设计——DDR 与 SRAM
linux·stm32·单片机·嵌入式硬件·网络协议
一路往蓝-Anbo11 小时前
第 8 章:M33 领航——引导 A35 加载 U-Boot 与 Linux 内核
linux·运维·服务器·stm32·单片机·嵌入式硬件·网络协议
liron7112 小时前
自定义MCP协议的一点想法
网络
The_Uniform_C@t213 小时前
论文浅读(第三期)|摘自《UAV Resilience Against Stealthy Attacks》(第一节)
网络·物联网·学习·网络安全
闲人编程13 小时前
任务监控与错误重试
linux·服务器·网络·celery·任务队列·任务监控·错误重试