设置套接字超时的第三个技术是使用套接字选项 SO_RCVTIMEO 与 SO_SNDTIMEO,它的优势在于一次设置,所有应用于该套接字的操作都自动带有超时时间。它就好像是一个全局开关。
比如对于 SO_RCVTIMEO 来说,如果设置了它,所有对该套接字的读操作在规定的时间里没完成,就直接返回并设置 errno = EWOULDBLOCK
,对于 SO_SNDTIMEO 选项来说也是一样。
1. 程序路径
代码托管在 gitos 上,请使用下面的命令获取:
git clone https://git.oschina.net/ivan_allen/unp.git
如果你已经 clone 过这个代码了,请使用 git pull
更新一下。本节程序所使用的程序路径是 unp/program/advcio/read_timeo/read_timeo_sockopt
.
2. 设置 SO_RCVTIMEO
- 设置 SO_RCVTIMEO 超时
sockfd = socket(/*...*/); // 设置超时时间为 5 秒 struct timeval tv; tv.tv_sec = 5; tv.tv_usec = 0; setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
经过一次性设置后,以后调用 read 系列的函数,最多只能阻塞 5 秒。对于 SO_SNDTIMEO 选项来说设置方法也是一样的。
- recvfrom 判断超时
如果 recvfrom 返回 EWOULDBLOCK,说明超时。
nr = recvfrom(sockfd, /*...*/); if (nr < 0) { if (errno == EWOULDBLOCK) { // 超时 } //... }
3. 实验结果
图1 使用套接字选项设置套接字超时
4. 总结
- 掌握使用套接字选项 SO_RCVTIMEO 与 SO_SNDTIMEO 控制套接字超时