67-套接字超时(select)
原创
©著作权归作者所有:来自51CTO博客作者mb63083a7dd962a的原创作品,请联系作者获取转载授权,否则将追究法律责任
设置超时的第二个技术是使用 select 函数。它使用了 select 函数的最后一个超时参数,对套接字描述符进行了“预读”。
1. 程序路径
如果你已经 clone 过这个代码了,请使用 Git pull 更新一下。本节程序所使用的程序路径是 unp/program/advcio/read_timeo/read_timeo_select
.
2. 伪代码
// 该函数利用 select 函数判断在 nsec 时间内描述符 fd 是否可读
int readable_timeo(int fd, int nsec) {
int
fd_set rfds;
struct timeval tv;
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
tv.tv_sec = nsec;
tv.tv_usec = 0;
ret = select(fd + 1, &rfds, NULL, NULL, &tv);
int recvfrom_timeo(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen, int nsec) {
int ret;
ret = readable_timeo(sockfd, nsec);
// select 函数返回 0,表示超时
if (ret == 0) {
errno = ETIMEDOUT;
ret = -1;
}
else {
ret = recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
}
return
3. 实验结果
read_timeo_select 是一个 udp 客户端,实际上就是前面的 udp/basic 程序,只不过它将 recvfrom 修改成了带超时的 recvfrom.
read_timeo_select 向 mars 主机发送了一个报文后,阻塞在 recvfrom_timeo 函数上,因为 mars 主机上的服务器并未启动,因此 read_timeo_select 永远也不可能收到 mars 主机发回的数据。
经历 5 秒的时候后,recvfrom_timeo 函数超时返回。
图1 带超时的 recvfrom 函数
4. 总结