由于平时UDP协议接触的少,最近在梳理网络编程知识的时候,发现好多之前没有深入了解过的问题,有的甚至颠覆了以前的网络编程知识。以下是几个很重要的知识点。

1 UDP的无连接

学过网络编程的朋友都知道,TCP是有连接的,而UDP协议是无连接的。那么这个连接究竟指的什么?

从编程的角度来说,连接指的是套接字描述符绑定了通信两端EndPoint的接口。例如TCP建立的连接一定是两个真实有效的两端,通过各自套接字的状态来维持。accept返回的套接字关联了一个四元组,即{(dst_ip, dst_port), (src_ip, src_port)}。

也就是说,在tcp建立连接的套接字上操作(read,write),肯定是在针对已建立的两端进行操作。

而UDP发送数据的时候是需要指定对方的ip地址和端口号的。对于服务器而言,UDP发送数据的一端已经通过bind函数绑定了ip地址和端口。所以UDP可以给任何目标地址发送数据,即使目标地址或端口不存在。

对于UDP同一个套接字,可以这次给一个目标地址发送消息,下次给另一个地址发送消息,而TCP根本是不可能的。

2 UDP也可以有连接

上面提到UDP发送的另一端每次调用时需要指定,能不能像TCP一样指定好通信的两端呢?用connect函数就可以做到。

其实connect函数会执行很多操作,如果没有bind,那么就会绑定一个本地端口。bind的第二个参数指定了要与之通信的远程IP地址和端口。通过getsockname和getpeername函数可以获得socket fd的连接的信息。

用connect绑定的socket fd,依然可以sendto其他目标地址,但是recvfrom时,只能是绑定的那个远程目标主机了。这与没有connect不同,给谁发送消息,socket fd的远程地址信息就是谁的,recvfrom就是最新一次的。例如同一个socket fd两次发送给不同的目标主机,那么每次发送之后就会改变绑定的远程地址信息。

3 UDP的分包

UDP数据的发送对应数据的接收,也就是说一次发送数据的调用只能对应一次数据的接收。网络数据链路层不是有MTU限制么,如果发送的数据包很大怎么办?他是如何分包的呢?

这个问题缘自一次实验。有一次发送2000字节的UDP数据,然而用tcpdump指定端口抓包,竟然只抓到一个数据包。到处找资料才知道原来是UDP数据分包时的格式问题.

我们设想一下, 如果应用层需要用UDP发送2000字节的数据, 那么加上IP头和UDP头后, 就是2028个字节了, 超过了MTU的限制, 那怎么办呢? 此时, 协议栈在IP层采用了分片的机制, 把大的应用数据拆分成若干个小的数据, 这样就有了若干个IP包, 而且会保证每个IP包不超过1500字节。用图来表示就是:

UDP协议解惑

可以看到, 数据包被分成了两个IP包来发送, 且第二个IP包没有UDP数据, 没有端口信息! 这一点十分值得注意。 如果过滤端口来抓包, 肯定抓不到这个IP包。 第一个包也会有点怪异, 他的IP头有分片的标志,其中UDP头中标明的包长度包含了第二个包的应用数据长度。

UDP数据被分包时,系统负责组包,所以接收数据的一方还是可以收到完整的数据,如果接收缓冲区不够大,那么数据将会被截断。

参考:

https://blog.csdn.net/stpeace/article/details/74152332

https://www.cnblogs.com/f-ck-need-u/p/7064286.html

https://www.cnblogs.com/red-code/p/7132023.html

https://www.cnblogs.com/liguangsunls/p/6951708.html

https://www.cnblogs.com/glacierh/p/3653442.html

https://blog.csdn.net/lell3538/article/details/53335472

 

 

相关文章:

  • 2022-12-23
  • 2021-11-19
  • 2021-04-07
猜你喜欢
  • 2021-11-19
  • 2021-07-30
  • 2021-07-15
  • 2021-08-22
相关资源
相似解决方案