商道如狼道 发表于 2025-1-4 08:39:20

【Linux】传输层协议UDP

目次
再谈端口号
端口号范围划分
UDP协议
UDP协议端格式
UDP的特点
UDP的缓冲区
UDP注意事项
进一步深刻理解

再谈端口号

https://i-blog.csdnimg.cn/direct/ed3866229c5741a4abca624e3e89fda5.png
在上图中,有两个客户端A和B,客户端A打开了两个欣赏器,这两个客户端都访问同一个服务器,都访问服务器的80端口,由于A和B的IP地点是不一样的,服务器在返回应答时就能根据双方的IP地点区分这两台不同的主机。同一台主机上两个不同的哀求对应的端口号不一样,服务器在应答时就可以准确把应答推送给特定端口号。在将来通过TCP/UDP通信时,TCP/UDP报文里会包罗端口信息,IP报文里会包罗源IP目的IP,构成了四元组,构成套接字通信。在客户端发起哀求时,要把服务器的IP和端口以及本身的IP和端口写进来,构成上图的报文,推送给服务器端,这就是服务器端为什么能收到你发来的数据也同时能知道你客户端的源IP和源端口号,也就知道这个消息是谁发的。这样的四元组一定出现在底层的网络报文中的。
别的,还有一个叫“协议号”的东西,会在IP首部里面有一个协议号,用来表明通信时接纳的上层协议是TCP/UDP的,方便把IP报文交给传输层。这样,在TCP/IP协议中,我们就可以通过用“源IP”、“源端口号”、“目的IP”、“目的端口号”、“协议号”这样一个五元组来标识一个通信,权衡通信的双方是谁、用什么协议来通信(可以通过netstat -n查看)。
https://i-blog.csdnimg.cn/direct/37b5cd8665da47b883cb9bd56dea73af.png
端口号范围划分



[*]0-1023:着名端口号,HTTP、FTP、SSH这些广为使用的应用层协议,它们的端口号是固定的。
[*]1024-65535:操纵系统动态分配的端口号。客户端的端口号,就是在这个范围内选择。
着名端口号
有些服务器非常常用,为了方便使用,人们约定了一些常见的服务器,一些常见的着名端口号:


[*]ssh服务器,使用22号端口
[*]ftp服务器,使用21号端口
[*]http服务器,使用80号端口
[*]https服务器,使用443号端口
使用cat /etc/services可以查看着名端口号都有哪些。
有两个问题:
   1.一个历程是否可以bind多个端口号?
可以,我们要的是从端口号到服务历程的唯一性。
   2.一个端口号是否可以被多个历程bind?
不可以,理由同上。
我们再来理解一下端口号和历程之间的关系,历程在系统内就是struct task_struct,可以认为OS维护了一张哈希表,key就是端口号,value就是历程pcb对应的地点。当底层有数据来了,报文里肯定携带了目的端口号,那目的端口号去查哈希表找到历程,就可以把数据交给历程。所以可以认为bind就是把port和历程pcb做关联。因为key值必须唯一,所以一个端口不能绑定多个历程。
UDP协议

UDP协议端格式

https://i-blog.csdnimg.cn/direct/9fa3d9c526ea4eccb86033d7a494e7e7.png
UDP的报头是一个结构体,报头里的每个字段都是结构体中的成员属性。通过源端口号和目的端口号就可以知道是哪个历程发的以及发给哪个历程。16位UDP长度,代表报文的总长度,包罗UDP首部+UDP数据。报头部分是8字节。如果校验出错,就直接丢弃,所以UDP不包管可靠性。
无论哪种协议,都必须解决两个子问题,

[*]如何将报头和有效载荷举行分离(封装)
[*]如何将有效载荷举行分用?
对于第1个问题,通过使用固定长度的报头(8字节)分离,前8个字节就是报头。UDP是面向数据报的,通过16位UDP长度包管读到的报文是完整的,整个报头的长度减去8字节就是有效载荷的长度。对于第2个问题,因为报文里包罗了16位目的端口号,找到对应的历程,就可以将数据分用到应用历程。
我们在来理解一个问题:在之前写套接字时,为什么端口号的类型是uint16_t呢?因为协议就是这么规定的!
UDP的特点



[*]无连接:知道对端的IP和端口号就可以直接举行通信,不需要创建连接。
[*]不可靠:没有确认机制,没有重传机制,如果因为网络故障该段无法发送到对方,UDP协议层也不会给应用层返回任何错误信息。
[*]面向数据报:应用层交给UDP多长的报文,UDP原样发送,既不会拆分,也不会合并。
用UDP传输100个字节数据:


[*]如果发送端调用一次 sendto, 发送 100 个字节, 那么接收端也必须调用对应的,一次 recvfrom, 接收 100 个字节; 而不能循环调用 10 次 recvfrom, 每次接收 10 个字节。
UDP的缓冲区

UDP没有真正意义上的发送缓冲区,调用sendto会直接交给内核,由内核将数据传给网络层协议举行后续的传输动作。但是有接收缓冲区,但这个接收缓冲区不能包管收到的UDP报和发送的UDP报顺序划一,如果缓冲区满了,再到达的UDP数据就会被丢弃。UDP支持全双工,可以同时读写。由于UDP不需要做可靠性包管,所以没有发送缓冲区。
UDP注意事项

UDP协议首部有一个16位的最大长度,所以UDP报文最大长度是2^16位(约64K,包罗UDP首部),所以单个UDP报文长度不能高出64K。如果高出64K,就需要在应用层手动分包,多次发送,在接收端手动拼装。
进一步深刻理解

1.udp报头
在举行UDP协议的交换时,用的是对结构体二进制流序列化和反序列化。可以这么做的原因是因为内核不涉及到业务,并且任何OS都是C语言写的,只要转化为网络序列就不会出错。OS的尺度化水平比较高。而应用层所用的语言不同,不同语言,不能统一,需要序列化和反序列化。
2.对报文的理解
OS内可能同时存在大量的报文,有的可能正在被向上交付,有的在被向下交付,所以OS要对报文举行管理,先形貌,在组织。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 【Linux】传输层协议UDP