阻塞通信模型的网络超时设置

阻塞通信模型的网络超时设置


阻塞通信模型中,connect、recv、recvfrom、send都是阻塞函数,当不具备条件时,程序会一直阻塞在这些函数调用里,无法执行后续内容。为了解决该问题,可采用非阻塞通信模型。当然,也可通过设置超时的方法解决阻塞问题。设置超时的方式有两种,一是利用select;二是利用setsockopt的SO_RCVTIMEO或SO_SNDTIMEO改变socket的属性。

select

select函数允许调用方等待多个事件中一个、多个发生或经历指定时间后才唤醒它。select可以操作多个不同类型的描述符集合,分别是读描述符集合、写描述符集合和异常描述符集合。

#include <sys/select.h>
#include <sys/time.h>
int select(int maxfd_add_1, fd_set * readset, fd_set * writeset, fd_set * exceptset, const struct timeval * timeout)

maxfd_add_1是后续三个描述符集合中最大描述符加1,从0到maxfd_add_1-1的描述符都被检测。
readset、writeset、exceptset指定内核测试的描述符,无需关注的可设置为NULL。针对fd_set的操作包括:
FD_ZERO(fd_set * fdset) //清空集合
FD_SET(int fd, fd_set * fdset) //将描述符加入集合
FD_ISSET(int fd, fd_set fdset) // 判断描述符集中的描述符是否满足I/0条件
FD_CLR(int fd, fd_set
fdset) //将描述符从集合中删除

struct timeval{
long tv_sec;//seconds
long tv_usec;//microseconds
};
timeout有三种使用方式:
(1)设置为NULL,select会一直阻塞,直至检测的描述符集中的描述符准备好I/O;
(2)将tv_sec和tv_usec都设置为0,select不等待,检测描述符后直接返回;
(3)将tv_sec或tv_usec设置为大于0的数,等待指定时间,直至描述符准备好I/O或已到等待期限;

setsockopt

设置套接字的选 项。选项可能存在于多层协议中,它们总会出现在最上面的套接字层。当操作套接字选项时,选项位于的层和选项的名称必须给出。为了操作套接字层的选项,应该将层的值指定为SOL_SOCKET。为了操作其它层的选项,控制选项的合适协议号必须给出。例如,为了表示一个选项由TCP协议解析,层应该设定为协议 号TCP。
#include <sys/socket.h>
int getsockopt(int sock, int level, int optname, void *optval, socklen_t *optlen);
int setsockopt(int sock, int level, int optname, const void *optval, socklen_t optlen);

参数:
sock:将要被设置或者获取选项的套接字。
level:选项所在的协议层。
optname:需要访问的选项名。
optval:对于getsockopt(),指向返回选项值的缓冲。对于setsockopt(),指向包含新选项值的缓冲。
optlen:对于getsockopt(),作为入口参数时,选项值的最大长度。作为出口参数时,选项值的实际长度。对于setsockopt(),现选项的长度。

SO_RCVTIMEO和SO_SNDTIMEO分别用来设置socket接收数据和发送数据的超时时间,仅对数据接收和发送相关的socket函数有效,这些函数包括 send,sendmsg,recv,recvmsg ,accept 和connect。针对不同的函数,超时后设置的errno不同。
在这里插入图片描述

设置描述符超时:
socklen_t optlen = sizeof(struct timeval);
struct timeval tv;
tv.tv_sec = 10800;
tv.tv_usec = 0;
setsockopt(socketfd, SOL_SOCKET, SO_RCVTIMEO, &tv, optlen);

select与setsockopt设置超时的区别

(1)setsockopt是修改套接字的属性,select是判断是否能进行某种操作,满足I/O条件后再调用阻塞函数;
(2)setsockopt只要设置一次即可;select是在阻塞函数前调用,每次调用阻塞函数前都需要先调用select;
(3)select同时操作多个描述符;
(4)setsockopt精度是毫秒级;select可设置更高的精度(微秒级);

猜你喜欢

转载自blog.csdn.net/cooperdoctor/article/details/85199499