UDP是一个简单(和TCP相比)协议,但是,UDP是被误解最多的一个协议,没有之一。
先来看一个小例子。
[centos@centosstream8 ~]$ netstat -paunt
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
udp 0 0 0.0.0.0:67 0.0.0.0:* -
udp0 0 192.168.231.129:68 192.168.231.254:67 ESTABLISHED -
意外不意外,加黑的UDP状态竟然是“ESTABLISHED”。
熟悉UDP协议的读者知道,这是一个用于DHCP Session的一个UDP连接。
DHCP Client是本机(192.168.231.129),使用UDP端口号68。
DHCP Server 的IP地址=192.168.231.254,侦听UDP端口号67。
这个UDP所谓的连接是如何建立的?
假设上文的DHCP Client在启动时,本地接口IP=0,也不知道DHCP Server的地址。
DHCP Client进程通过socket()命令创建一个UDP的Socket。
使用bind()命令,将端口68和socket.local_port绑定,socket.local_port =68。
使用 connect()命令,将端口67和socke.peer_port绑定,socket.peer_port =67。
由于不知道DHCP Server的地址,故需要使用广播IP地址255.255.255.255,目的端口号=67,发送一个DHCP Discovery报文。
Sendto --- > 255.255.255.255:67
在发送discovery的期间,socket的四元组信息如下:
-
socket.peer_ip =255.255.255.255
-
socket.local_ip =0
-
socket.peer_port =67
-
socket.local_port =68
发完这个消息,4元组变成什么样子的了?
-
socket.peer_ip =0 (是不是很意外,被reset为0了)
-
socket.local_ip =0
-
socket.peer_port =67
-
socket.local_port =68
为何要Reset为0啊?
咱们先看DHCP Server是如何回复DHCP Offer的?
-
UDP.Destination IP =0
-
UDP.Source IP =192.168.231.254
-
UDP.Destination port =68
-
UDP.Source port =67
这个UDP四元组能被上文socket四元组过滤进来(filer-in)吗?
当然可以的。
如果没有上文的Reset 0操作,这个返回的DHCP Offer报文将被丢弃!!!
因为255.255.255.255 与 192.168.231.254不match。
而 0 与 192.168.231.254 match,0代表wildcard,代表一切。
通过discovery、offer、request、ack 四次消息,最后DHCP Client获得的IP = 192.168.231.129.
好戏结束了吗?
没有!
DHCP Client会将socket的local_ip 与192.168.231.129 bind起来。
对,读者没有猜错。依然需要使用bind()命令:
socket.local_ip =192.168.231.129
还有吗?
由于DHCP Client已经知道DHCP Server的地址,故需要使用connect绑定起来。
socket.peer_ip =192.168.231.254
事已至此,重新审视一下这个socket。
-
socket.local_ip =192.168.231.129
-
socket.peer_ip =192.168.231.254
-
socket.peer_port =67
-
socket.local_port =68
由于这个socket四元组唯一,与TCP连接的四元组特征一样(唯一性),故netstat将它的状态设置为“ESTABLISHED”。
使用Connected UDP socket好处是,将DHCP Server的地址信息记录在socket里,下次续租时,直接使用send()命令即可,而不会像sendto()需要提供服务器的IP地址。
使用Connected UDP socket还有一个好处,其它服务器的DHCP报文无法插入该连接。
有好处自然有害处,Connected UDP Socket一旦其中的一方变更了IP地址或者端口号,通信就中断了。移动通信的漫游电话,由于在漫游过程中IP地址可能变更,会造成通信障碍。故使用Un-Connected UDP Socket会更合适。
什么是Un-Connected UDP Socket?
一句话,除了socket.local_port ≠0,其它三元组 =0。
最后,UDP Socket 的connect()是否和TCP的connect()一样,也会发送报文的?
No,不会发送。
UDP的connect()和bind()原理类似,前者是绑定对端(peer)的IP/UDP信息,后者是绑定本机(local)的IP/UDP信息。
原文始发于微信公众号(车小胖谈网络):面向连接需要建立一条线路,udp是无连接的,为什么也需要socket建立线路?
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论