UDP的超时设置
2016-06-23 09:40
429 查看
最近在做项目的时候,遇到一个问题:就是阻塞模式下的UDP在接收(recvfrom)的时候,如果没有收到数据包,程序会一直阻塞。
在Windows下可以通过设置超时时间来解决这个问题。
但是在wince6.0上,上面的代码不起效果,然后上网查了一下,可以用select来解决UDP的阻塞问题,在wince6.0上也支持。
select函数可以监视需要监视的文件描述符的变化情况,读写或是异常。文件描述符,在windows上即文件句柄,socket就是一个文件描述符。
参数列表
int nfds: 是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1,不能错!在Windows中这个参数的值无所谓,可以忽略,通常设置为0。
fd_set* readfds: 需要监视读变化的文件描述符的集合,比如需要监视一个socket的数据接收,就可以将这个socket加入到这个集合中。如果不关心任何文件描述符的读变化,可以传入NULL。
fd_set* writefds:需要监视写变化的文件描述符的集合,比如需要监视一个socket的数据发送,就可以将这个socket加入到这个集合中。如果不关心任何文件描述符的写变化,可以传入NULL。
fd_set* exceptfds:同上面两个参数类似,监视异常的文件描述符的集合。
const struct timeval* timeout:设置select的超时时间,
1)传入NULL值:将设置select为阻塞状态,一直等到监视的文件描述符集合中的某个文件描述符发生变化;
2)传入0秒0毫秒:select变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;
3)timeout的值大于0:就是等待的超时时间,即 select在timeout时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管怎样一定返回;
返回值
< 0:select发生错误。
> 0:监视的文件描述符发生变化。
= 0:等待超时,监视的文件描述符没有变化。
UDP接收数据包的代码
在Windows下可以通过设置超时时间来解决这个问题。
struct timeval TimeOut; TimeOut.tv_sec = 1; TimeOut.tv_usec = 0; ::setsockopt(sockServer, SOL_SOCKET, SO_RCVTIMEO, (char *)&TimeOut, sizeof(TimeOut));
但是在wince6.0上,上面的代码不起效果,然后上网查了一下,可以用select来解决UDP的阻塞问题,在wince6.0上也支持。
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, const struct timeval* timeout);
select函数可以监视需要监视的文件描述符的变化情况,读写或是异常。文件描述符,在windows上即文件句柄,socket就是一个文件描述符。
参数列表
int nfds: 是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1,不能错!在Windows中这个参数的值无所谓,可以忽略,通常设置为0。
fd_set* readfds: 需要监视读变化的文件描述符的集合,比如需要监视一个socket的数据接收,就可以将这个socket加入到这个集合中。如果不关心任何文件描述符的读变化,可以传入NULL。
fd_set* writefds:需要监视写变化的文件描述符的集合,比如需要监视一个socket的数据发送,就可以将这个socket加入到这个集合中。如果不关心任何文件描述符的写变化,可以传入NULL。
fd_set* exceptfds:同上面两个参数类似,监视异常的文件描述符的集合。
const struct timeval* timeout:设置select的超时时间,
1)传入NULL值:将设置select为阻塞状态,一直等到监视的文件描述符集合中的某个文件描述符发生变化;
2)传入0秒0毫秒:select变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;
3)timeout的值大于0:就是等待的超时时间,即 select在timeout时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管怎样一定返回;
返回值
< 0:select发生错误。
> 0:监视的文件描述符发生变化。
= 0:等待超时,监视的文件描述符没有变化。
UDP接收数据包的代码
bool RecvMsg(char* recvbuf) { fd_set fdRead; timeval timeout; timeout.tv_sec = 3 timeout.tv_usec = 0; while(true) { FD_ZERO(&fdRead); FD_SET(m_sock, &fdRead); int ret = select(0, &fdRead, NULL, NULL, &timeout); if(ret == SOCKET_ERROR) { return false; } else if(ret == 0)//超时 { return false; } else if(ret > 0) { if(FD_ISSET(m_sock, &fdRead)) { SOCKADDR_IN addrSrv; int nLen = sizeof(addrSrv); int nRecvBytes = recvfrom(m_sock, recvbuf, RECVBUFFER_SIZE, 0, (SOCKADDR*)&addrSrv, &nLen); if(nRecvBytes == SOCKET_ERROR || nRecvBytes <= 0) { return false; } else { return true; } } } } return false; }
相关文章推荐
- 【学习笔记】Java数组
- 浅谈Python中用datetime包进行对时间的一些操作
- Install Flash on Ubuntu and Dockerfile
- view的背景
- #android##bug#返回最后的换行符
- FileUpload总结
- Git之reset
- Alpha阶段项目总结
- js日历,使用datepicker.js,ui.core.js,jquery-1.7.1.js
- Java学习笔记(9)Objects and Classes
- 一个很棒的 Android APP框架
- iOS UITextView 限制最大输入字数
- Android 数据存储(一)之文件存储
- 怎么样说服别人
- Django 模板过滤器列表
- PHP基础之数据类型与输出
- 键盘上回车按钮的js触发事件
- Android实战技巧:深入解析AsyncTask
- Ubuntu下Eclipse的安装方法(图文详解)
- php微信简单接口