当前位置: 首页 > news >正文

Socket、UDP、TCP协议和简单实现基于UDP的客户端服务端

目录

Socket

TCP和UDP区别

UDP:无连接,不可靠传输,面向数据报,全双工

TCP:有连接,可靠传输,面向字节流,全双工

无连接和有连接

可靠传输和不可靠传输 

面向数据报和面向字节流 

全双工和半双工

Java中对于传输层的一些API 

DatagramSocket 

DatagramSocket构造方法 

send()和receive()方法

close()方法 

DatagramPacket 

 DatagramPacket构造方法

实现一个UDP客户端-服务端的代码 

明确服务端做的事

UDP服务端代码编写 

明确客户端做的事 

UDP客户端代码编写 

通信结果: 

为什么客户端不需要指定一个特定的端口号呢? 


Socket

我们都知道用户在进行网络通信的时候,应用层会将报文发送给传输层,发送的这个过程,应用层需要调用操作系统的一些api,准确来说就是调用传输层的api,应用层和传输层之间沟通调用的api就是Socket。严格意义上讲,socket的api属于传输层。

TCP和UDP就是Socke的apit提供的两种不同的风格。

TCP和UDP区别

UDP:无连接,不可靠传输,面向数据报,全双工

TCP:有连接,可靠传输,面向字节流,全双工

无连接和有连接

无连接:不确保接收方是否接收到信息。比如发短信,发微信都是无连接通信,不需要对方在线什么的就能直接把要传递的信息发送出去

有连接:确保接收方会收到信息 。比如打电话,打视频,需要对方接起才能让双方进行信息的传递

原因:UDP协议当中发送方和接收方的运输层进程之间没有建立握手,只负责把应用层的报文打包成UDP报文段进行发送,不关注接收方是否能收到,所以UDP协议是无连接的。而TCP协议在传输数据之前会进行“三次握手”来确保接收方是能够收到信息的,所以TCP协议是有连接的

可靠传输和不可靠传输 

可靠传输就是发送方发送完信息后,接收方如果收到了信息,发送方可以知晓接收方已经收到了信息,比如有些聊天的已读功能

不可靠传输就是发送方发送完信息后,不知道接收方是否收到了信息,比如微信聊天,发送方并不知道接收方是否接受到信息。

面向数据报和面向字节流 

UDP协议就是面向数据报的协议。

传输层协议是以数据报为基本单位进行传输的,操作系统不会对消息进行拆分,也就是直接把应用层传过来的报文打包为UDP数据段,然后传输到网络层 

而TCP协议是面向字节流的协议。

TCP把数据看成一个没有结构的,但是有序的字节流。

当使用TCP协议进行传输的时候,一条应用层消息可能会被操作系统分成多个TCP报文。也就是说应用层发送过来的报文会被拆分成多个数据段,比如:|

应用层打算发送Hello This is Java,使用TCP协议就有可能拆分成两个TCP段:

也有可能只有一个TCP段。

而对于UDP协议是不会拆分的:

全双工和半双工

全双工:一个通信通道可以双向传输(既可以发送,又可以接收) 比如很多道路都是可以双向通行的

半双工:通信通道只能单向传输(只能发送或接收) 比如青藏铁路这样的,只能单向通行。

Java中对于传输层的一些API 

DatagramSocket 

在操作系统中一切皆为文件。

使用DatagramSocket这个类,可以创建socket对象,操作系统中把这个socket当做一个文件来处理,相当于文件描述符表上的某一项。 

使用一个socket对象就可以和另外一个主机进行通信了,如果要和多个主机进行通信,可以创建多个socket对象。 

DatagramSocket构造方法 

DatagramSocket()   系统自动分配一个空闲的端口号

DatagramSocket(int port)   指定端口号,将socket和对应的端口相关联。

send()和receive()方法

void send(DatagramPacket packet)  代表socket发送应用层报文的方式
void receive(DatagramPacket packet) 代表socket接收应用层报文的方式

需要发送/接收的DatagramPackett就是一个应用层报文。 

close()方法 

用于关闭文件描述符表项,释放进程当中的文件描述符表项所占用的空间。

DatagramPacket 

表示的是UDP当中传输的一个应用层报文 

 DatagramPacket构造方法

DatagramPacket(byte[] buf,int length)把buf数组作为地址
DatagramPacket(byte[] buf,int offset,int length,SocketAddress)把buf数组作为地址,并且指定了需要传输的目标主机IP和端口号

实现一个UDP客户端-服务端的代码 

假设约定:客户端是运行在用户手中的,服务器是运行在我们程序员自己的电脑 。

明确服务端做的事

1、读取客户端的请求

2、根据请求计算响应

3、将响应返回给客户端 

需要指定的属性:DatagramSocket socket(socket对象) 用来为客户端提供socket来接收应用层报文

构造方法当中初始化socket对象,并且指定本机当中需要建立通信的端口号。 

 注意:应用层和传输层建立连接的时候一定要指明socket端口号,不然就会导致选用无参构造方法,无法明确UDP和应用层的哪个端口建立联系,从而无法通信。 

UDP服务端代码编写 

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketAddress;
import java.net.SocketException;public class UdpEchoServer2 {//与服务端建立联系的socketprivate DatagramSocket datagramSocket;//使用构造方法并传入端口(关联端口)public UdpEchoServer2(int port) throws SocketException {//创建对象datagramSocket=new DatagramSocket(port);//port是服务端进程端口号}//创建start方法作为服务器启动public void start() throws IOException {System.out.println("服务器启动!");while(true){//1、packet存放接收应用层内容DatagramPacket receivePacket=new DatagramPacket(new byte[4096],4096);//2、使用socket来接收应用层信息并将其存放在packet的byte数组中datagramSocket.receive(receivePacket);//3、截取byte数组中应用层信息的实际长度的内容,比如hello就截取hello长度的内容//也就是获取数据报的实际长度部分String request = new String(receivePacket.getData(),0,receivePacket.getLength());//4、模拟回显服务器,将提取出来的数据报传给process进行处理并把响应赋值给responseString response= process(request);//5、将响应字符串转化为字节数组byte[] responseByte=response.getBytes();//6、获取响应数组长度int responseByteLength= responseByte.length;//7、获取对应的客户端的IP和端口号(SocketAddress)根据packet的信息获取对应的地址SocketAddress address = receivePacket.getSocketAddress();//8、构造返回给客户端的socket对象DatagramPacket responsePacket=new DatagramPacket(responseByte,responseByteLength,address);//9、使用构造的socket对象将响应发送给客户端datagramSocket.send(responsePacket);//输出处理结果作为验证System.out.println("客户端IP:"+receivePacket.getAddress()+"客户端端口号:"+receivePacket.getPort());}}//服务器响应public String process(String request){return "udp服务器已响应"+request;}//服务端启动public static void main(String[] args) throws IOException {UdpEchoServer2 udpEchoServer2=new UdpEchoServer2(9090);udpEchoServer2.start();}}

启动服务端:(指定服务器端口号为9090)此时启动后服务器正常启动,但是由于客户端没有向服务端发送任何请求,所以服务端会在receive方法出进行阻塞等待。

    public static void main(String[] args) throws IOException {UdpEchoServer2 udpEchoServer2=new UdpEchoServer2(9090);udpEchoServer2.start();}

  

明确客户端做的事 

客户端主要做的事就是和服务端建立通信,并且为服务端的receive方法内部的数据(DatagramPacket)等待服务端的send方法发送数据(DatagramPacket)回来并做出响应

UDP客户端代码编写 

import java.io.IOException;
import java.net.*;
import java.util.Scanner;public class UdpEchoClient {/*** 客户端需要有的属性:* 1、和服务端建立联系的socket* 2、服务端的ip地址* 3、服务端的端口号*/private DatagramSocket socket;//和服务端建立联系的socketprivate String serverIp;//服务端的ip地址(目的IP)private int serverPort;//服务端的端口号(目的端口)//构造方法public UdpEchoClient(String serverIp,int serverPort) throws SocketException {socket=new DatagramSocket();this.serverIp=serverIp;this.serverPort=serverPort;}//启动客户端public void start() throws IOException {System.out.println("客户端已启动!");Scanner input=new Scanner(System.in);while(true){//1.用户从控制台输入想要发送给服务端的数据System.out.println("请输入您想要发送给服务端的数据:");String request= input.next();//2、构造Udp请求//将请求转为请求数组byte[] requestBytes=request.getBytes();//获取请求数组的长度int length= requestBytes.length;//3、指定服务端的ip和端口号DatagramPacket requestPacket=new DatagramPacket(requestBytes,length,InetAddress.getByName(serverIp),serverPort);//4、将请求发送到服务端的receive方法中socket.send(requestPacket);//5、读取并接收服务端的响应结果DatagramPacket responsePacket=new DatagramPacket(new byte[4096],4096);//存放读取的结果//接收服务端的响应socket.receive(responsePacket);//6、构造响应的字符串String response=new String(responsePacket.getData(),0,responsePacket.getLength());//7、输出响应的字符串System.out.println(response);}}public static void main(String[] args) throws IOException {UdpEchoClient udpEchoClient=new UdpEchoClient("127.0.0.1",9090);udpEchoClient.start();//客户端启动}}

先启动服务端,再启动客户端,否则无法顺利完成通信。

通信结果: 

 

客户端和服务端通信的流程图解:

 

为什么客户端不需要指定一个特定的端口号呢? 

首先,客户端指定特定的端口号,如果该端口号被占用,那么就无法取得和服务端的通信了,会抛出BindException异常。其次,客户端是不可控的,因为客户端往往是有很多台的,不同客户端的程序运行情况我们是不知道的,无法有效的进行控制,这些不受到我们程序员的控制,所以不如让客户端自由分配一个可以使用的端口号即可,而服务端是可控的,程序员可以手动的控制服务端的端口占用情况是非常方便的,如果是随机分配的反而会提高程序员的工作难度。 

相关文章:

Socket、UDP、TCP协议和简单实现基于UDP的客户端服务端

目录 Socket TCP和UDP区别 UDP:无连接,不可靠传输,面向数据报,全双工 TCP:有连接,可靠传输,面向字节流,全双工 无连接和有连接 可靠传输和不可靠传输 面向数据报和面向字节流…...

发布订阅模式:观察者模式的一种变体

发布-订阅模型(Publish-Subscribe Model)的底层机制通常基于观察者模式。 发布-订阅模型是观察者模式的一种变体。 在观察者模式中,主题(或被观察者)维护了一组观察者,当主题的状态发生变化时&#xff0c…...

TiDB离线部署、Tiup部署TiDB

先做tidb准备工作: 部署 TiDB 前的环境检查操作:TiDB 环境与系统配置检查 | PingCAP 文档中心 1.查看数据盘 fdisk -l (2,3)本人的分区已经是 ext4 文件系统不用分区,具体官方文档的分区: 4.查看数据盘…...

10GBase-T万兆电口模块助力数据中心实现高效数据传输

10GBase-T万兆电口模块一种高速、高效的网络连接解决方案,具有快速传输速度和稳定可靠的特点。它可以在数据中心中广泛应用,提供出色的网络性能和可扩展性,为数据中心的发展做出了重要的贡献。 一、10GBase-T万兆电口模块的特点与优势 高速传…...

使用Docker中部署GitLab 避坑指南

在容器化的世界中,Docker已经成为了我们部署和管理应用程序的首选工具。然而,在使用Docker部署GitLab时,我们可能会遇到一些问题,本文将为你提供一份详细的避坑指南。网上的教程有的都没说清楚,或者干脆是错的。摸索了…...

我的NPI项目之设备系统启动(八) -- Android14的GKI2.0开发步骤和注意事项

GKI是什么? Google为什么要推行GKI? GKI全称General Kernel Image。GKI在framework和kernel之间提供了标准接口,使得android OS能够轻松适配/维护/兼容不同的设备和linux kernel。 Google引入GKI的目的是将Framework和Kernel进一步的解耦。因…...

鼠标右键助手专业版 MouseBoost PRO for Mac v3.3.6中文破解

MouseBoost Pro mac版是一款简单实用的鼠标右键助手专业版,MouseBoost Pro for Mac只要轻点你的鼠标右键,就可以激活你想要的各种功能,让你的工作效率大幅度提高,非常好用。 软件下载:MouseBoost PRO for Mac v3.3.6中…...

React学习计划-react-hooks补充

React Hooks 1. 使用hooks理由 高阶组件为了复用,导致代码层级复杂生命周期的复杂 2. useState(保存组件状态) const [state, setstate] useState(initialState)3. useEffect(处理副作用)和useLayoutEffect(同步执行副作用) 使用方式: useEffect(…...

KTV点歌系统vue+springboot音乐歌曲播放器系统

目前现有的KTV点歌系统对于用户而言其在线点歌流程仍然过于繁琐,对于歌曲而言其系统安全性并不能保障。同时整套系统所使用的技术相对较为落后,界面不能动态化展示。相比较于其它同类型网站而言不能体现技术先进性。 1.2 项目目标 KTV点歌系统的后台开发…...

vue video 多个视频切换后视频不显示的解决方法

先说一下我这边的需求是视频需要轮播&#xff0c;一个人员有多个视频&#xff0c;左右轮播是轮播某个人员下的视频&#xff0c;上下切换是切换人员。 vue 代码 <el-carouselindicator-position"none"ref"carousel"arrow"always":interval&qu…...

多态与代码屎山

到底什么是多态呢?多态是面向未来的,比如企业采购为例: 一般分为线上合线下两种, 我们设计一个父类叫做"采购", 里面做一些共通的处理: 申请, 承认, 支付, 购买方式. 然后让各自的子类(线上,线下)实现自己的方法.实际调用过程中传入不同的对象就可以.到此为止项目开…...

Git基本操作(2)

Git基本操作&#xff08;2&#xff09; 上交文件之后&#xff0c;git文件的变化git cat-file HEAD指针里面有啥文件被修改git statusgit diff 文件名 版本回退&#xff08;git reset&#xff09;撤销回退git reflog 撤销的三种情况还没有addgit checkout -- [file] 已经add还没…...

编程笔记 Golang基础 023 切片

编程笔记 Golang基础 023 切片 一、切片二、定义与初始化三、基本操作四、示例 Go语言中的切片&#xff08;slices&#xff09;是基于数组的抽象数据类型&#xff0c;它提供了一种灵活的方式来处理可变长度的数据序列。切片本身不存储任何数据&#xff0c;而是指向底层数组的一…...

qt 软件发布(Windows)

1. 开发环境 QtCreator MSVC编译器 2. 源码编译 生成release或者debug版本的exe可执行文件(x64或x86) 3. windeployqt 打包 ①左下角开始菜单栏找到QT的命令交互对话框&#xff0c;如下图MSVC 2017 64-bit(根据第二步编译的类型选择64位或者32位)。 ②cd 切换到第二步可…...

《汇编语言》- 读书笔记 - 第11章-标志寄存器

《汇编语言》- 读书笔记 - 第11章-标志寄存器 标志寄存器指令与标志位关系11.1 ZF&#xff08;Zero Flag&#xff0c;零标志位&#xff09;11.2 PF&#xff08;Parity Flag&#xff0c;奇偶标志位&#xff09;11.3 SF&#xff08;Sign Flag&#xff0c;符号标志位&#xff09;处…...

1.QT简介(介绍、安装,项目创建等)

1. QT介绍 Qt&#xff08;官方发音 [kju:t]&#xff09;是一个跨平台的C开发库&#xff0c;主要用来开发图形用户界面&#xff08;Graphical User Interface&#xff0c;GUI&#xff09;程序 Qt 是纯 C 开发的&#xff0c;正常情况下需要先学习C语言、然后在学习C然后才能使用…...

【服务器】服务器推荐

一、引言 在数字世界的浪潮中&#xff0c;服务器作为数据存储和处理的基石&#xff0c;其重要性不言而喻。而在这个繁星点点的市场中&#xff0c;雨云以其独特的优势和超高的性价比&#xff0c;逐渐成为众多企业和个人的首选。今天&#xff0c;就让我带你走进雨云的世界&#…...

信号系统之线性图像处理

1 卷积 图像卷积的工作原理与一维卷积相同。例如&#xff0c;图像可以被视为脉冲的总和&#xff0c;即缩放和移位的delta函数。同样&#xff0c;线性系统的特征在于它们如何响应脉冲。也就是说&#xff0c;通过它们的脉冲响应。系统的输出图像等于输入图像与系统脉冲响应的卷积…...

uniapp腾讯地图JavaScript Api,H5端和原生APP端可用

因项目需要&#xff0c;在uniapp中集成使用腾讯地图&#xff0c;为了方便维护&#xff0c;希望通过一套代码实现H5和APP同时可用。H5显示相对简单&#xff0c;APP端比较麻烦&#xff0c;记录下实现过程 一、集成步骤 1.使用 renderjs script标签使用renderjs&#xff0c;因为…...

MyBatisPlus:PG数组类型自动映射问题

引言: PostGreSQL数据库提供了丰富的数据类型,通过查看官网文档,我们也可以发现,PG也提供了对数组类型的支持。 但是在实际开发中,我们通常是使用MyBatis/MyBatisPlus这种半自动ORM映射框架来实现数据库/表数据基本的增删改查,以及其它操作。那么,问题来了,如何…...

**发散创新:策略即代码——用 Rust实现动态权限控制引擎**在现代软件系统中,权限管理早已不是简单的“用

发散创新&#xff1a;策略即代码——用 Rust 实现动态权限控制引擎 在现代软件系统中&#xff0c;权限管理早已不是简单的“用户-角色-资源”映射。越来越多的业务场景要求我们具备灵活、可扩展、易维护的权限决策机制。传统硬编码方式难以应对频繁变更的业务规则&#xff0c;而…...

幻兽帕鲁启动提示 msvcp140.dll 丢失怎么办?2026最新解决办

心问题&#xff1a; 在 Steam 或其他平台启动《幻兽帕鲁》&#xff08;Palworld&#xff09;时&#xff0c;系统弹出“由于找不到 msvcp140.dll&#xff0c;无法继续执行代码”的错误提示&#xff0c;导致游戏无法进入。 简短回答&#xff1a; 幻兽帕鲁 msvcp140.dll 报错的主…...

PyTorch 2.8镜像法律科技:庭审音视频→AI摘要+关键帧提取+证据链可视化

PyTorch 2.8镜像法律科技&#xff1a;庭审音视频→AI摘要关键帧提取证据链可视化 1. 镜像概述与法律科技应用场景 在司法数字化进程中&#xff0c;庭审音视频处理正面临三大挑战&#xff1a;海量数据难以快速消化、关键信息提取效率低下、证据呈现方式单一。PyTorch 2.8深度学…...

Kook Zimage 真实幻想 Typora文档集成方案

Kook Zimage 真实幻想 Typora文档集成方案 1. 引言 技术文档写作最头疼的是什么&#xff1f;文字描述得再生动&#xff0c;也不如一张直观的图片来得有说服力。传统的文档创作流程中&#xff0c;我们需要先在专门的AI绘图工具中生成图片&#xff0c;然后下载保存&#xff0c;…...

错位排序算法

首先&#xff0c;让我们理解什么是错位排列&#xff1a;错位排列是指在排列中&#xff0c;任何一个元素都不在自己原来的位置上。比如&#xff0c;对于序列 {1,2,3}{1,2,3}&#xff0c;一个错位排列可能是 {3,1,2}{3,1,2}&#xff0c;因为 11 不在位置 11 上&#xff0c;22 不在…...

别再到处找转换工具了!用Audacity把WAV无损转成MP3,保姆级图文教程

音频处理新手指南&#xff1a;Audacity无损转换WAV到MP3的完整方案 你是否曾经下载了一段高质量录音&#xff0c;却发现文件体积大得惊人&#xff0c;根本无法通过邮件发送&#xff1f;或者尝试上传播客内容时&#xff0c;平台总是提示"文件格式不支持"&#xff1f;这…...

SEO_新手必看的SEO优化入门教程与常见误区

什么是SEO优化&#xff1f; SEO优化&#xff0c;全称搜索引擎优化&#xff0c;是指通过优化网站内容和结构&#xff0c;使其在搜索引擎&#xff08;如百度、谷歌&#xff09;中获得更高排名的一系列活动。SEO的目的是提高网站的自然流量&#xff0c;从而增加潜在客户和销售机会…...

Clawdbot惊艳效果:Qwen3-32B在医疗问诊摘要与术语标准化输出实测

Clawdbot惊艳效果&#xff1a;Qwen3-32B在医疗问诊摘要与术语标准化输出实测 1. 测试背景与平台介绍 Clawdbot是一个统一的AI代理网关与管理平台&#xff0c;为开发者提供直观的界面来构建、部署和监控自主AI代理。这个平台集成了聊天界面、多模型支持和强大的扩展系统&#…...

认知内耗:在亚马逊,为何品牌名内部的“关键词”正在相互厮杀

在亚马逊的品牌丛林中&#xff0c;最隐蔽的悲剧莫过于&#xff1a;你精心构思的品牌名&#xff0c;其内部的各个组成部分&#xff08;如“欧文斯”、“康宁”、“玻璃纤维”&#xff09;&#xff0c;并未协同指向你&#xff0c;反而各自激活了消费者心智中其他更强大品牌的“认…...

如何将微信聊天记忆转化为数字珍藏:WeChatMsg的数据主权革命

如何将微信聊天记忆转化为数字珍藏&#xff1a;WeChatMsg的数据主权革命 【免费下载链接】WeChatMsg 提取微信聊天记录&#xff0c;将其导出成HTML、Word、CSV文档永久保存&#xff0c;对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we…...