【Java】面向UDP接口的网络编程
【Java】面向UDP接口的网络编程
- 一. 基本通信模型
- 二. API
- DatagramSocket
- DatagramPacket
- 三. 回显服务器/客户端示例
- 服务器
- 客户端
- 总结
一. 基本通信模型
- UDP协议是面向数据报的,因此此处要构建数据报(Datagram)在进行发送。
二. API
DatagramSocket
DatagramSocket 是UDP Socket,⽤于发送和接收UDP数据报。
DatagramSocket
构造⽅法:
⽅法签名 | ⽅法说明 |
---|---|
DatagramSocket() | 创建⼀个UDP数据报套接字的Socket,绑定到本机任意⼀个随机端⼝(⼀般⽤于客⼾端) |
DatagramSocket(int port) | 创建⼀个UDP数据报套接字的Socket,绑定到本机指定的端⼝(⼀般⽤于服务端) |
DatagramSocket
⽅法:
⽅法签名 | ⽅法说明 |
---|---|
void receive(DatagramPacket p) | 从此套接字接收数据报(如果没有接收到数据报,该⽅法会阻塞等待) |
void send(DatagramPacket p) | 从此套接字发送数据报包(不会阻塞等待,直接发送) |
void close() | 关闭此数据报套接字 |
DatagramPacket
DatagramPacket是UDP Socket发送和接收的数据报。
DatagramPacket
构造⽅法:
⽅法签名 | ⽅法说明 |
---|---|
DatagramPacket(byte[] buf, int length) | 构造 DatagramPacket用于接收长度为 length数据包。 |
DatagramPacket(byte[] buf,int length, SocketAddress address) | 构造数据报包,用于将长度为 length的数据包发送到指定主机上的指定端口号。address指定⽬的主机的IP和端⼝号 |
DatagramPacket(byte[] buf, int length, InetAddress address, int port) | 构造一个数据报包,用于将长度为 length的数据包发送到指定主机上的指定端口号。 |
DatagramPacket
⽅法:
⽅法签名 | ⽅法说明 |
---|---|
InetAddress.getAddress() | 从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取接收端主机IP地址 |
int getPort() | 从接收的数据报中,获取发送端主机的端⼝号;或从发送的数据报中,获取接收端主机端⼝号 |
byte[] getData() | 获取数据报中的数据 |
三. 回显服务器/客户端示例
服务器
服务器端往往需要经历三个步骤:
- 读取客户端发来的请求并解析
//没有请求在receive处阻塞等待DatagramPacket requestPacket=new DatagramPacket(new byte[4096],4096);socket.receive(requestPacket);//读取到的字节数组转成String,方便后的逻续辑处理//getLength()得到的是有效长度String request=new String(requestPacket.getData(),0,requestPacket.getLength());
此处构造一个DatagramPacket用来接收请求,如果没有请求,则进入阻塞等待状态。
- 根据请求计算响应
String response=process(request);
根据不同的业务场景,来设计不同的计算过程,可以将计算过程单独写一个方法:
//根据不同的需求,设计不同的计算处理
//此处只是将请求返回,来观察通信过程
public String process(String request) {return request;
}
- 把响应返回给客户端
//构造一个 DatagramPacket 作为响应对象
DatagramPacket responsePacket=new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());
socket.send(responsePacket);
- [可选]打印日志
System.out.printf("[%s:%d] req:%s, rsep:%s\n",requestPacket.getAddress().toString(),requestPacket.getPort(),request,response);
完整代码:
import java.io.IOException;
import java.net.*;public class UdpEchoServer {//socket为网卡private DatagramSocket socket=null;public UdpEchoServer(int port) throws SocketException {socket=new DatagramSocket(port);}//服务器启动逻辑public void start() throws IOException {System.out.println("server has been started!");while(true){//循环一次,请求一个请求-响应过程//1.读取请求并解析//没有请求在receive处阻塞等待DatagramPacket requestPacket=new DatagramPacket(new byte[4096],4096);socket.receive(requestPacket);//读取到的字节数组转成String,方便后的逻续辑处理//getLength()得到的是有效长度String request=new String(requestPacket.getData(),0,requestPacket.getLength());//2.根据请求计算响应,此处只是简单的返回请求String response=process(request);//3.把响应返回给客户端//构造一个 DatagramPacket 作为响应对象DatagramPacket responsePacket=new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());socket.send(responsePacket);//打印日志System.out.printf("[%s:%d] req:%s, rsep:%s\n",requestPacket.getAddress().toString(),requestPacket.getPort(),request,response);}}//根据不同的需求,设计不同的计算处理public String process(String request) {return request;}public static void main(String[] args) throws IOException {UdpEchoServer server=new UdpEchoServer(10100);server.start();}
}
- 对于服务器端,往往会指定端口,便于客户端的访问。
客户端
客户端要从控制台读取客户的请求,因此需要经历四个步骤:
- 从控制台读取要发送的请求
Scanner scanner=new Scanner(System.in);
System.out.print(">");
//1.从控制台读取要发送的请求
if (!scanner.hasNext()) {break;}
String request=scanner.next();
- 构造数据报并发送
DatagramPacket requestPacket=new DatagramPacket(request.getBytes(),request.getBytes().length,InetAddress.getByName(serverIP),serverPort);
socket.send(requestPacket);
此处的serverIP和serverPort在构造方法处得到,这也是为什么我们要给服务器写一个指定的端口。
- 读取服务器的响应
DatagramPacket responsePacket=new DatagramPacket(new byte[4096],4096);
socket.receive(responsePacket);
- 把响应打印在控制台上
String response =new String(responsePacket.getData(),0,responsePacket.getLength());
System.out.println(response);
完整代码:
import java.io.IOException;
import java.net.*;
import java.util.Scanner;public class UdpEchoClient{private DatagramSocket socket=null;private String serverIP;private int serverPort;public UdpEchoClient(String serverIP,int serverPort) throws SocketException {this.serverIP=serverIP;this.serverPort=serverPort;//客户端随机分配端口socket=new DatagramSocket();}public void start() throws IOException {System.out.println("client has been started!");Scanner scanner=new Scanner(System.in);while(true) {System.out.print(">");//1.从控制台读取要发送的请求if (!scanner.hasNext()) {break;}String request=scanner.next();//2.构造请求并发送DatagramPacket requestPacket=new DatagramPacket(request.getBytes(),request.getBytes().length,InetAddress.getByName(serverIP),serverPort);socket.send(requestPacket);//3.读取服务器的响应DatagramPacket responsePacket=new DatagramPacket(new byte[4096],4096);socket.receive(responsePacket);//4.把响应打印在控制台上String response =new String(responsePacket.getData(),0,responsePacket.getLength());System.out.println(response);}}public static void main(String[] args) throws IOException {//环回IPUdpEchoClient client=new UdpEchoClient("127.0.0.1",10100);client.start();}
}
- 客户端是不需要指定端口的,是因为:指定的端口有可能被占用,且客户端往往由客户使用(不一定懂代码)。
- "127.0.0.1"是回显地址,即本机地址。
总结
构造DatagramPacket的三种方法的使用场景:
⽅法签名 | ⽅法说明 |
---|---|
DatagramPacket(byte[] buf, int length) | 构造 DatagramPacket用于接收长度为 length数据包。 |
DatagramPacket(byte[] buf,int length, SocketAddress address) | 构造数据报包,用于将长度为 length的数据包发送到指定主机上的指定端口号。address指定⽬的主机的IP和端⼝号 |
DatagramPacket(byte[] buf, int length, InetAddress address, int port) | 构造一个数据报包,用于将长度为 length的数据包发送到指定主机上的指定端口号。 |
- 第一种常用于服务器接收请求/客户端接收响应
- 第二种常用于服务器构造响应的数据报(由于接收了客户端的请求,可以读取到客户端的IP和端口号)
- 第三种常用于客户端构造请求的数据报(需要自行输入服务器的IP和端口号)
运行时,要先运行服务器,再运行客户端:
相关文章:

【Java】面向UDP接口的网络编程
【Java】面向UDP接口的网络编程 一. 基本通信模型二. APIDatagramSocketDatagramPacket 三. 回显服务器/客户端示例服务器客户端总结 一. 基本通信模型 UDP协议是面向数据报的,因此此处要构建数据报(Datagram)在进行发送。 二. API DatagramSocket DatagramSocke…...

SRS服务器搭建
1、配置 listen 1935; max_connections 1000; #srs_log_tank file; #srs_log_file ./objs/srs.log; daemon on; http_api { enabled on; listen 1985; } http_server { enabled on; listen 808…...

iMazing只能苹果电脑吗 Win和Mac上的iMazing功能有区别吗
在当今数字时代,管理和备份手机数据变得越来越重要。无论是转移照片、备份短信,还是管理应用程序,一个强大的工具可以大大简化这些操作。iMazing作为一款备受好评的iOS设备管理软件,已经成为许多用户的选择。但是,许多…...

ChatGPT可以分析股票吗?
结合国庆前大A股市的小波牛市以及今天的股市表现,我从多个角度为你提供一些分析和建议: 一、国庆前的小波牛市分析 国庆前,大A股市出现了一波小幅上涨,市场呈现出一些积极的信号: 政策面利好:政府出台了…...

Dockerfile搭建镜像
Dockerfile搭建镜像的优势与区别 引言 在现代软件开发与运维中,容器化技术日益普及,而Docker作为最流行的容器化平台之一,通过Dockerfile提供了一种灵活、自动化的方式来构建Docker镜像。Dockerfile使得镜像的构建过程可重复、可版本化&…...

Kubernetes-Kind篇-01-kind搭建测试集群
1、Kind 介绍 官方文档地址:https://kind.sigs.k8s.io/ github仓库地址:https://github.com/kubernetes-sigs/kind 国内镜像仓库地址:https://gitcode.com/gh_mirrors/ki/kind/overview kind 是一种使用 Docker 容器 nodes 运行本地 Kubern…...

在UniApp中高效处理大量文件请求的策略
在开发跨平台应用时,尤其是在使用UniApp这样的框架时,我们可能会遇到需要同时请求多个文件的情况。然而,不加节制地同时发起大量请求可能会带来严重的性能问题,如界面卡顿、内存溢出、网络带宽饱和等。本文将探讨如何在UniApp中高…...

docker compose入门4—常用命令
在使用 Docker Compose 管理多容器应用时,常见的命令帮助我们高效地管理容器的生命周期、服务、日志等。以下是一些常用的 Docker Compose 命令及其详细讲解: 1. docker-compose up 这个命令用于启动定义在 docker-compose.yml 文件中的服务。 用法&am…...

wps文本框文字居中对齐
直接点对齐里的水平居中,垂直居中是将文本框水平垂直居中,文字不会居中 将文本框里的文字居中: 垂直居中: 水平居中:...

注册信息页面
知识点: !+Enter 直接生成前端基本框架 1.<h1></h1> (2,3,4,5) 表示各级标题 2.<form></form> 表单建立 3.<input type" "></input> 表格(表单嵌套表格) type属…...

详解Java中的BIO、NIO、AIO
1、 详解Java中的BIO、AIO、NIO 1.1、引言 IO流是Java中比较难理解的一个知识点,但是IO流在实际的开发场景中经常会使用到,比如Dubbo底层就是NIO进行通讯。本文将介绍Java发展过程中出现的三种IO:BIO、NIO以及AIO,重点介绍NIO。…...

CAN和CANFD如何转换和通信
随着科技的发展,汽车电子和工业领域中CAN通信需要承载数据量也越来越大,传统CAN通信有了向CANFD通信过渡的倾向。在实现过渡的过程中可能会出现自己设备是CAN通信,客户设备是CANFD通信的情况,或者自己设备是CANFD通信,…...

QDateTimeEdit Class
Header:#include qmake:QT += widgets Inherits:QAbstractSpinBox Inherited By:QDateEdit and QTimeEdit Public Types enum Section {NoSection, AmPmSection, MSecSection, SecondSection, MinuteSection, …, YearSection } flags SectionsProperties calendarPopu…...

Windows环境安装CentOS7
【注意】安装CentOS需要先安装Vmware虚拟机 【下载前准备】 一、下载CentOS 7镜像文件阿里云镜像开源,点击跳转 二、安装VMware(17): a. 官网,点击跳转 b. 许可证:JU090-6039P-08409-8J0QH-2YR7F 安装V…...

用docker启动mysql步骤
以下是在 Docker 中启动 MySQL 的详细步骤: **一、拉取 MySQL 镜像 ** 1. 打开终端,确保 Docker 服务正在运行。可以使用以下命令检查 Docker 服务状态: sudo systemctl status docker 2. 使用以下命令拉取 MySQL 官方镜像: d…...

[Linux] Linux 初识进程地址空间 (进程地址空间第一弹)
标题:[Linux] Linux初识进程地址空间 个人主页水墨不写bug (图片来源于AI) 目录 一、什么是进程地址空间 二、为什么父子进程相同地址的变量的值不同 三、初识虚拟地址、页表 一、什么是进程地址空间 其实,在很久之前…...

力扣21~25题
21题(简单): 分析: 按要求照做就好了,这种链表基本操作适合用c写,python用起来真的很奇怪 python代码: # Definition for singly-linked list. # class ListNode: # def __init__(self, v…...

04. prometheus 监控 Windows 服务器
prometheus 监控 Windows 服务器 1. 下载安装 Windows_exporter 安装包下载:https://github.com/prometheus-community/windows_exporter/releases 下载 msi 版本,上传至要监控的 Windows 服务器,双击安装即可,exporter 会自动…...

【机器学习】——决策树以及随机森林
文章目录 1. 决策树的基本概念与结构1.1 决策树的构建过程 2. 决策树的划分标准2.1 信息增益(Information Gain)2.2 信息增益比(Information Gain Ratio)2.3 基尼指数(Gini Index)2.4 均方误差(…...

怎么选择合适的数据恢复软件?适用于 Windows 的数据恢复软件对比
针对 Windows 的领先数据恢复软件的全面回顾: 丢失重要数据对任何 Windows 用户来说都是一场噩梦。从意外删除到系统崩溃,数据丢失是一个非常普遍的问题。值得庆幸的是,有强大的数据恢复工具可以帮助找回丢失的文件。这篇评论深入探讨了适用于…...

CI/CD 和 DevOps 工具概述:Jenkins 、Docker 的概述、工作流程、对比
随着软件开发的复杂性不断增加,持续集成(CI)、持续交付(CD)和运维(Ops)的概念逐渐成为现代软件开发流程中的核心组成部分。这些概念促进了开发团队与运维团队之间的协作,提升了软件的…...

基于SpringBoot+Vue+uniapp的高校教务管理小程序系统设计和实现
2. 详细视频演示 文章底部名片,联系我获取更详细的演示视频 3. 论文参考 4. 项目运行截图 代码运行,效果展示图 代码运行,效果展示图 代码运行,效果展示图 代码运行,效果展示图 代码运行,效果展示图 5. 技…...

如何在 Ubuntu VPS 上从 Apache Web 服务器迁移到 Nginx
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 简介 在启动网站或应用程序时,您需要做出许多选择。有时,您的需求会发生变化,新技术变得可行&#x…...

pikachu靶场总结(一)
最近看到好多人还在打这个靶机所以把以前写的总结放上来了,主要是皮卡丘靶场漏洞的原理,利用方式,防护方法简略总结,纯手敲记录,总结如果不到位请评论区留言! 一、暴力破解 1.基于表单的暴力破解 原理&a…...

No.2 笔记 | 网络安全攻防:PC、CS工具与移动应用分析
引言 在当今数字化时代,网络安全已成为每个人都应该关注的重要话题。本文将总结一次关于网络安全攻防技术的学习内容,涵盖PC端和移动端的恶意程序利用,以及强大的渗透测试工具Cobalt Strike的使用。通过学习这些内容,我们不仅能够了解攻击者的手法,更能提高自身的安全意识和防…...

QD1-P8 HTML格式化标签
本节学习:HTML 格式化标签。 本节视频 www.bilibili.com/video/BV1n64y1U7oj?p8 一、font 标签 用途:定义文本的字体大小、颜色和 face(字体类型)。 示例 <!DOCTYPE html> <html><head><meta cha…...

WordPress修改固定链接后301的重定向方法
网站改版实际上是很忌讳的,尤其是针对已被搜索引擎收录的网站,新站不用考虑这些问题,而已经收录的网站网页在不遵守搜索引擎规则的前提下,是会被降权,关键词排名下滑、流量IP会被剥夺、收录会减少 、业务成交量会急剧下…...

关于Allegro导出Gerber时的槽孔问题
注意点一: 如果设计的板子中有 槽孔和通孔(俗称圆孔),不仅要NC Drill, 还要 NC Route allegro导出的槽孔文件后缀是 .rou 圆型孔后缀 是 .drl ,出gerber时需要看下是否有该文件。 注意点二: 导出钻孔文件时,设置参…...

平时使用的正则总结
1、将某一个字符串的后缀名后面加上“!400_500” 使用场景是将minio拿过来的图片压缩尺寸从而压缩其大小,加快渲染的速度。需要在图片的后缀名后面加上尺寸如下: const str //storage-test.test.shiqiao.com/gateway/common/isopen/2024/10/09/e708e9…...

[万字解析]从零开始使用transformers微调huggingface格式的中文Bert模型的过程以及可能出现的问题
系列文章目录 使用transformers中的pipeline调用huggingface中模型过程中可能遇到的问题和修改建议 [万字解析]从零开始使用transformers微调huggingface格式的中文Bert模型的过程以及可能出现的问题 文章目录 系列文章目录前言模型与数据集下载模型下载数据集下载 数据加载、…...