UDP实现简单的超时重传
众所周知~UDP是一个无连接协议,因此靠它来传输的话是不可靠的,即使是数据包丢失 也不会报错。但是,在编写Linux上的socket程序时,却可以用简单的方法,在应用层实现超时 重传,让UDP可靠一些。(这次说的方法最好用于两个程序间通信——也许只能用 于两台机器通信)首先~我介绍一下Linux下,I/O操作的阻塞模式: 在Linux下,I/O 操作有四种模式,分别为:阻塞式I/O,非阻塞式I/O,多路复用I/O,一击信号驱动I/O,这 次需要用到的是阻塞式I/O。阻塞式I/O是最简单,最常用但也是效率最低的一个。在默认模 式下,所有的套接字都是阻塞模式,即:当用户调用这些函数时,函数将一直阻塞下去,直 至有某个事件发生。具体事件依函数而定,比如:调用读函数,由于缓存中还没有数据,而 使得读函数发生读阻塞;同理,也可能在调用写函数的时候发生写阻塞;除此之外,还有调 accept函数的时候,由于没有客户连接服务器,使得其发生阻塞;调用connect函数时,由于 三次握手没有结束,使得其发生阻塞等等。也就是说~在没有特定事件发生的情况下,函数 将什么也不干而等待事件发生,事件发生后则继续执行程序。而有些时候,由于某些原因, 会使得函数永远处于阻塞模式(比如:客户用UDP给服务器传送数据的数据丢失,使得服务器 端的recvfrom函数始终处于阻塞模式)这就需要调用某些函数使这些函数不再阻塞,具体方 法有: 1、使用信号:比如调用alarm函数 2、在套接字上设置SO_RCVTIMEO和 SO_SNDTIMEO选项,使得其阻塞有时间限制 3、时间选择通过select函数来实现 好啦~阻塞式I/O就说到这里,言归正传~继续讨论相对可靠一些的UDP~ 前 面已经说了,假如使用阻塞模式,那么,当一个数据包还没有到达目的地时,那么数据包的 目的端程序就会处于阻塞状态,因此不能调用sendto函数给发送端,而发送端此时也在 recvfrom下阻塞了,等待对方传来消息。 由于前面已经说了,这是只有两个程序间通 信,因此,双方程序的生死之大事、前途、命运……都掌握在传输的那个数据 包上了,如果那个数据包不争气(没准是路由问题,线路问题等等),中途数据包丢失了, 那么,双方都将永远处于阻塞状态:发送端阻塞在recvfrom上,等待接收端回话;接收端也 阻塞在recvfrom上,等待发送端传来的消息。可偏偏那消息不争气,传不过来 ……难道这俩程序就这么挂了? 如果只有sendto,recvfrom函数而没有 超时机制,那……就为这俩程序祈祷吧……大约他们俩就得挂这 等关机或者被处以极刑(就是kill啊~)…………不过~听了我 下面说的~就可以解决这问题~同时,让UDP层上面的应用层有超时重传的能力~(晕~我这 不是作广告啊………………) 其实看到这里 ,大家已经多半想到了如何处理这问题:只要有一方退出阻塞模式,发个数据包,那两个程 序就都解放了~怎么让一个程序退出阻塞模式呢~其实很简单啦~没错~可以用alarm函数~ 一旦到时间~给程序传一个SIGALRM的中断消息就可以啦~让程序先处理这消息,然后拦一下 SIGALRM消息,爱怎么处理怎么处理~解决~ /****************函数:alarm函数( 知道的可以不用看)****************/ #include <unistd.h> unsigned int alarm(unsigned int seconds); 功能:从调 用该函数算起,seconds秒后返回向调用进程传送一个SIGALRM消息 参数:seconds以 秒为单位的整数 /****************************************************************/ 看到这里也许你以为一切都解决了,但是还有一个容易被人忽视的问题:在Linux中,默认处 理中断的方式是: 当从中断调用返回时,继续执行被 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |