59-UDP 数据报丢失

1. 程序路径

代码托管在 gitos 上,请使用下面的命令获取:

git clone https://git.oschina.net/ivan_allen/unp.git

如果你已经 clone 过这个代码了,请使用 git pull 更新一下。本节程序所使用的程序路径是 unp/program/echo_udp/basic

2. UDP 数据报丢失

UDP 是不可靠的,它不像 TCP 能够保证数据一定到达对端接收缓冲区。上一节我们写的 basic/echo 程序就会遇到这样的问题:客户端无法确认发送的数据是否到达对端接收缓冲区。

实际上,每个 UDP 套接字都有一个接收缓冲区,所有到达该套接字的数据报按顺序进入缓冲区。当进程调用 recvfrom 时,缓冲区中的下一个数据报以 FIFO(先进先出)顺序返回给进程。

回到我们的 basic/echo 客户端,它的伪代码像下面这样:

while(1) {
  gets(buf);// 从标准输入读入数据
  sendto(sockfd, buf, servaddr); // 发送给服务器
  recvfrom(sockfd, buf, NULL); // 接收数据
  puts(buf);
}

如果客户端在 sendto 的时候,udp 报文没有顺利到达对方,那么客户端将永远阻塞在 recvfrom 上。

3. 实验

在 sun 主机上启动客户端,给一个 ip 地址不存在或者端口不存在的服务器发信息。

  • 主机存在,服务器未启动(端口不存在)
$ ./echo -h mars


这里写图片描述
图1 主机存在,服务器未启动

可以看到,tcpdump 产生了一个 ICMP 报文:udp 端口不可达的信息。可惜的是,此错误并没有报告给应用程序。sendto 的返回值根本检测不到这种情况。

  • 主机不存在(flower 还没有开机)
$ ./echo -h flower


这里写图片描述
图2 flower 还没开机

服务器不存在,tcpdump 发送 ARP 请求报文,此错误也不会报告给应用进程~

上面两种情况,导致客户端阻塞在了 recvfrom 上,永远没有继续执行的机会。

当然,这个实验并没有真正的模拟数据报丢失的情况,要想在服务器启动的情况下模拟数据报丢失是很难的,我们不妨假设服务器启动了,但是到服务器的某个中间路由器正好宕机了,那么这种情况就非常像前面的两个实验了。

4. 如何解决问题?

有一些可用的解决方案,比如给 recvfrom 设置超时。如果超过一定的时间,recvfrom 还没有返回,基本上就可以认为数据报丢失,重新回到 sendto 继续执行。

还有一种方案是使用多线程,我们将发送和接收放到两个不同的线程中去执行。

还有其它更多的方案,比如给 udp 增加可靠性,模拟 tcp 协议,给 udp 程序添加两个特性:超时和和重传、序列号。

这些话题我们现在保留,以后继续讨论。

5. 总结

  • UDP 数据报会丢失
  • UDP 是不可靠的
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值