UDP数据报套接字

2023-12-06 00:36
文章标签 数据 udp 接字 报套

本文主要是介绍UDP数据报套接字,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • DatagramSocket API
    • DatagramPacket API
    • 示例一: 请求响应
      • UDP服务端
      • UDP客户端

DatagramSocket API

Socket是操作系统中的一个概念,本质上是一种特殊的文件,Socket就属于把“网卡”这个设备给抽象成了文件。往 Socket 文件中写数据,就相当于通过网卡发数据,从 Socket 文件中读数据,就相当于通过网卡接收数据。而在Java中,就使用 DatagramSocket 这个类来表示系统内部的 Socket 文件。

DatagramSocket 构造方法

方法方法说明
DatagramSocket()创建一个UDP数据报的Socket,绑定到本机任意一个随机端口(一般用于客户端)
DatagramSocket(int port)创建一个UDP数据报的Socket,绑定到本机指定的端口(一般用于服务端)

DatagramSocket 方法:

方法方法说明
void receive(DatagramPacket p)使用DatagramPacket这个类来表示一个UDP数据报(如果没有接收到数据报,该方法会阻塞等待)
void send(DatagramPacket p)从此套接字中发送数据报(不会阻塞等待,直接发送)
void close()关闭数据报套接字

DatagramPacket API

DatagramPacket 构造方法:

方法方法说明
DatagramPacket(byte[] buf, int length)构造一个DatagramPacket 用来接收数据报,接收的数据保存在字节数组中,指定接收长度(第二个参数length)
DatagramPacket(byte[] buf, int offset, int length, SocketAddress address)构造一个DatagramPacket 用来发送数据报,发送的数据为字节数组(第一个参数buf)中,从0到指定长度(第二个参数 length),address指定目的主机的IP和端口号

DatagramPacket 方法:

方法方法说明
InetAddress getAddress()从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取接收端主机IP地址
int port()从接收的数据报中,获取发送端主机的端口号;或从发送的数据报中,获取接收端主句端口号
byte[] getData()获取数据报中的数据

示例一: 请求响应

任务需求:

1.在客户端这边,从键盘上输入一个路径

2.发送请求,将这个路径构造成数据报发送给服务器

3.服务器接收到请求并计算响应:根据该请求数据,如果是一目录,列出目录中所包含的所有文件及文件夹,如果是一个普通文件,列出文件所在目录中的所有文件及文件夹

4.服务端返回响应:遍历子文件和子文件夹,每个文件名一行,作为响应的数据报返回给客户端

5.客户端接收响应:打印出所有的文件及文件夹

注意:为了解决空字符或读取请求时读取的字符串长度不够,造成数据丢失的情况,这里约定,客户端和服务端发送的数据都已 ‘/3’ 进行结尾,读取到 ‘/3’ 就表示请求或响应都全部读取完成

UDP服务端

public class UdpEchoServer {//1.创建一个DatagramSocket,用于后续接收和发送UDP数据报private static DatagramSocket socket;private static DatagramPacket requestPacket;public UdpEchoServer(int port) throws SocketException {//在服务器这边使用Socket,一般要显示的指定端口号//在客户端,不需要显示的指定端口号,系统会自动分配一个端口号socket = new DatagramSocket(port);}public static void start() throws IOException {while(true) {//2.创建数据报,用于接收客户端发来的数据报byte[] dataRequest = new byte[4024];requestPacket = new DatagramPacket(dataRequest, dataRequest.length);System.out.println("----------------------------------------");System.out.println("等待服务端接收数据");//3.等待客户端发来的数据报,在服务端收到数据报之前,receive()方法会一直阻塞等待,直到收到数据报后,// DatagramPacket对象中,包含客户端发来的数据,客户端IP地址和端口号socket.receive(requestPacket);System.out.println("客户端IP:" + requestPacket.getAddress().getHostAddress());System.out.println("客户端端口号:" + requestPacket.getPort());//7. 根据请求,计算响应for(int i = 0; i < dataRequest.length; i++) {byte b = dataRequest[i];if(b == '\3') {//7.1 读取请求:读取到约定好的结束符'\3',取结束符前的所有内容String request = new String(dataRequest, 0 , i);System.out.println("请求的路径:" + request);//7.2 根据请求计算响应File requestFile = new File(request);File[] children = null;//7.3 判断该路径是否存在if(requestFile.exists()) {if(!requestFile.isDirectory()) {//表示该对象是一个普通文件//获取上级目录路径String parent = requestFile.getParent();requestFile = new File(parent);}children = requestFile.listFiles();}else {String res = "该路径错误!!!" +'\n' + '\3';sendEcho(res);break;}//7.4 构造响应内容,将每个子文件作为一行StringBuilder response = new StringBuilder();for(File child : children) {response.append(child.getName() + '\n');}//7.5 读取完之后,加上约定的结束符response.append('\3');//7.6 发送返回的响应数据sendEcho(response.toString());break;}}}}public static void sendEcho(String response) throws IOException {//构造响应数据报byte[] responseData = response.getBytes(StandardCharsets.UTF_8);DatagramPacket responsePacket = new DatagramPacket(responseData, responseData.length, requestPacket.getSocketAddress());//发送返回的响应数据报socket.send(responsePacket);System.out.println("发送完成");}public static void main(String[] args) {try {UdpEchoServer echoServer = new UdpEchoServer(8888);} catch (SocketException e) {throw new RuntimeException(e);}try {UdpEchoServer.start();} catch (IOException e) {throw new RuntimeException(e);}}
}

UDP客户端

public class UdpEchoClient {//4.创建客服端Socket//4.1指定服务端端地址和端口号private static final SocketAddress ADDRESS = new InetSocketAddress("127.0.0.1", 8888);private static DatagramSocket socket;public UdpEchoClient() {//客户端不需要指定端口号try {socket = new DatagramSocket();} catch (SocketException e) {throw new RuntimeException(e);}}public static void start() throws IOException {Scanner in = new Scanner(System.in);while(true) {//5.构建数据报System.out.println("请输入要展开的目录");//5.1 为了接收端能获取到有效的内容,以\3作为结束符;String request = in.nextLine() + '\3';//5.2 将要发送的数据转换成字节,并指定字符集byte[] requestData = request.getBytes(StandardCharsets.UTF_8);//5.3 组装好的数据包中包含了数据,及发送服务端的信息(IP地址、端口号)DatagramPacket requestPacket = new DatagramPacket(requestData, requestData.length, ADDRESS);//6.发送数据报socket.send(requestPacket);System.out.println("--------------------------------");//8.接收服务端响应的数据报,打印出响应内容//8.1 使用字节数组接收响应数据byte[] responseData = new byte[4090];//8.2 构建响应数据报DatagramPacket responsePacket = new DatagramPacket(responseData, responseData.length);//8.3 接收响应socket.receive(responsePacket);//8.4 打印出响应内容System.out.println("该目录下的文件列表为:");//因为,响应中的每个文件都是以回车结尾的,next用于定义每个文件起始位置,int next = 0;for(int i = 0; i < responseData.length; i++) {byte b = responseData[i];if(b == '\3') {//表示响应读取完成break;}if(b == '\n') {//遇见回车键表示读取到了一个文件名//构建字符串文件名String print = new String(responseData, next, i - next);System.out.println(print);//下次解析从换行后的索引开始next = i + 1;}}}}public static void main(String[] args) {UdpEchoClient echoClient = new UdpEchoClient();try {UdpEchoClient.start();} catch (IOException e) {throw new RuntimeException(e);}}
}

在这里插入图片描述

这篇关于UDP数据报套接字的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/459754

相关文章

使用Java解析JSON数据并提取特定字段的实现步骤(以提取mailNo为例)

《使用Java解析JSON数据并提取特定字段的实现步骤(以提取mailNo为例)》在现代软件开发中,处理JSON数据是一项非常常见的任务,无论是从API接口获取数据,还是将数据存储为JSON格式,解析... 目录1. 背景介绍1.1 jsON简介1.2 实际案例2. 准备工作2.1 环境搭建2.1.1 添加

MySQL中删除重复数据SQL的三种写法

《MySQL中删除重复数据SQL的三种写法》:本文主要介绍MySQL中删除重复数据SQL的三种写法,文中通过代码示例讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下... 目录方法一:使用 left join + 子查询删除重复数据(推荐)方法二:创建临时表(需分多步执行,逻辑清晰,但会

Java实现任务管理器性能网络监控数据的方法详解

《Java实现任务管理器性能网络监控数据的方法详解》在现代操作系统中,任务管理器是一个非常重要的工具,用于监控和管理计算机的运行状态,包括CPU使用率、内存占用等,对于开发者和系统管理员来说,了解这些... 目录引言一、背景知识二、准备工作1. Maven依赖2. Gradle依赖三、代码实现四、代码详解五

详谈redis跟数据库的数据同步问题

《详谈redis跟数据库的数据同步问题》文章讨论了在Redis和数据库数据一致性问题上的解决方案,主要比较了先更新Redis缓存再更新数据库和先更新数据库再更新Redis缓存两种方案,文章指出,删除R... 目录一、Redis 数据库数据一致性的解决方案1.1、更新Redis缓存、删除Redis缓存的区别二

Redis事务与数据持久化方式

《Redis事务与数据持久化方式》该文档主要介绍了Redis事务和持久化机制,事务通过将多个命令打包执行,而持久化则通过快照(RDB)和追加式文件(AOF)两种方式将内存数据保存到磁盘,以防止数据丢失... 目录一、Redis 事务1.1 事务本质1.2 数据库事务与redis事务1.2.1 数据库事务1.

Oracle Expdp按条件导出指定表数据的方法实例

《OracleExpdp按条件导出指定表数据的方法实例》:本文主要介绍Oracle的expdp数据泵方式导出特定机构和时间范围的数据,并通过parfile文件进行条件限制和配置,文中通过代码介绍... 目录1.场景描述 2.方案分析3.实验验证 3.1 parfile文件3.2 expdp命令导出4.总结

更改docker默认数据目录的方法步骤

《更改docker默认数据目录的方法步骤》本文主要介绍了更改docker默认数据目录的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1.查看docker是否存在并停止该服务2.挂载镜像并安装rsync便于备份3.取消挂载备份和迁

不删数据还能合并磁盘? 让电脑C盘D盘合并并保留数据的技巧

《不删数据还能合并磁盘?让电脑C盘D盘合并并保留数据的技巧》在Windows操作系统中,合并C盘和D盘是一个相对复杂的任务,尤其是当你不希望删除其中的数据时,幸运的是,有几种方法可以实现这一目标且在... 在电脑生产时,制造商常为C盘分配较小的磁盘空间,以确保软件在运行过程中不会出现磁盘空间不足的问题。但在

Java如何接收并解析HL7协议数据

《Java如何接收并解析HL7协议数据》文章主要介绍了HL7协议及其在医疗行业中的应用,详细描述了如何配置环境、接收和解析数据,以及与前端进行交互的实现方法,文章还分享了使用7Edit工具进行调试的经... 目录一、前言二、正文1、环境配置2、数据接收:HL7Monitor3、数据解析:HL7Busines

Mybatis拦截器如何实现数据权限过滤

《Mybatis拦截器如何实现数据权限过滤》本文介绍了MyBatis拦截器的使用,通过实现Interceptor接口对SQL进行处理,实现数据权限过滤功能,通过在本地线程变量中存储数据权限相关信息,并... 目录背景基础知识MyBATis 拦截器介绍代码实战总结背景现在的项目负责人去年年底离职,导致前期规