admin 管理员组文章数量: 1086019
2023年12月19日发(作者:initqueue)
网络编程Socket之UDP(三)超时设置和非阻塞
前面遗留的两个问题:
1.一个已连接UDP套接字能且仅能与一个对端交换数据报,那么客户端发送广播的时候如何防止recvfrom方法阻塞;
2.服务端忙的时候,已连接的UDP套接字也会被阻塞。
方法一:设置超时
UNP 14.2
There are three ways to place a timeout on an I/O
operation involving a socket:
arm, which generates theSIGALRMsignal
when the specified time hasexpired. This involves signal
handling, which can differ from oneimplementation to the
next, and it may interfere with other existing calls toalarmin
the waiting for I/O inselect, which has a
time limit built-in, instead
ofblocking in a call toread
orwrite.
the newerSO_RCVTIMEO
andSO_SNDTIMEO
socket options. The problemwith this approach is that not
all implementations support these two socket options.
第一种方法我们可以用ios提供的定时器来实现;
第二种方法在recvfrom方法调用前添加代码如下,这里是设置3秒超时:
[cpp] view plain copy <span style="font-size:12px;">
fd_set read_fdset; struct timeval timeout;
FD_ZERO(&read_fdset);
FD_SET(socketFileDescriptor, &read_fdset);
_sec = 3; _usec = 0;
int ret; do { ret =
select(socketFileDescriptor + 1, &read_fdset, NULL,
NULL, &timeout); } while (ret <
0 && errno == EINTR); if
(ret == 0) { printf("time outn");
return -1; } </span> 第三种方法代码如下:
[cpp] view plain copy <span style="font-size:12px;">
struct timeval timeout = {3,0};
setsockopt(socketFileDescriptor, SOL_SOCKET,
SO_RCVTIMEO, (char *)&timeout, sizeof(struct
timeval));</span> 设置3秒超时,如果3秒以后无法读到数据,recvfrom方法返回-1,而且errno返回EWOULDBLOCK错误
[cpp] view plain copy <span style="font-size:12px;">
n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);
if (n < 0) { if (errno == EWOULDBLOCK)
{ printf("time outn"); return
-1; } else
err_sys("recvfrom error"); }</span> 方法二:使用非阻塞式IO
UNP 16.1With a nonblocking socket, if the input operation
cannot be satisfied (at leastone byte of data for a TCP
socket or a complete datagram for a UDP socket),we see
an
immediate return with an error of EWOULDBLOCK. 首先设置非阻塞套接字:
[cpp] view plain copy <span style="font-size:12px;">
int ret; int flags = fcntl(socketFileDescriptor,
F_GETFL); if (flags == -1)
{ printf("fcntl error"); return -1; }
flags |= O_NONBLOCK; ret =
fcntl(socketFileDescriptor, F_SETFL, flags); if (ret ==
-1) { printf("fcntl error"); return
-1; }</span> 然后运行,打印信息如下:>>
send success
>> recvfrom fail--errno = 35
>> send success
>> recvfrom fail--errno = 35
>> send success
>> recvfrom fail--errno = 35
>> send success
>> recvfrom fail--errno = 35
>> send success
>> server
said:01&c0:5e:79:fc:0e:0c&192.168.0.1&iShare-R1B011D2199
>> send success
>> recvfrom fail--errno = 35
>> send success
>> recvfrom fail--errno = 35
>> send success
>> recvfrom fail--errno = 35会发现recvfrom方法返回失败的概率很大,而且errno返回EWOULDBLOCK错误,这是因为在非阻塞的情况下有可能因为服务器阻塞导致客户端这边的UDP套接字的接收缓冲区为空, 因此为了解决这个问题我们在recvfrom方法之前添加如下代码:
[cpp] view plain copy <span style="font-size:12px;">
fd_set read_fdset;
FD_ZERO(&read_fdset);
FD_SET(socketFileDescriptor, &read_fdset);
int ret; do { ret =
select(socketFileDescriptor + 1, &read_fdset, NULL,
NULL, NULL); } while (ret < 0
&& errno == EINTR); if (ret
== 0) { printf("time outn");
return -1; }</span> 然后运行,打印信息如下:>> send success
>> server
said:01&c0:5e:79:fc:0e:0c&192.168.0.1&iShare-R1B011D2199
>> send success
>> server
said:01&c0:5e:79:fc:0e:0c&192.168.0.1&iShare-R1B011D2199
>> send success
>> server
said:01&c0:5e:79:fc:0e:0c&192.168.0.1&iShare-R1B011D2199
>> send success
>> server
said:01&c0:5e:79:fc:0e:0c&192.168.0.1&iShare-R1B011D2199
>> send success
>> server
said:01&c0:5e:79:fc:0e:0c&192.168.0.1&iShare-R1B011D2199参考:
《UNIX Network ProgrammingVolume 1, Third Edition:
TheSockets Networking API》
版权声明:本文标题:网络编程Socket之UDP(三)超时设置和非阻塞 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.roclinux.cn/b/1702968032a437815.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论