您的位置:首页 > 理论基础 > 计算机网络

【Linux网络编程】超时检测

2017-04-11 20:30 190 查看
在网络编程中超时检测是一个比较常见的操作,因为网络连接具有很大的不确定性,而很多网络操作函数默认都是阻塞式的,因此如果不设置超时,可能会造成永久等待状态出现。

设置套接字选项

setsockopt

【注意】如果程序一直执行,设置的套接字选项一直有效,对所有跟套接字描述符相关的操作都有效

int setsockopt(int socket, int level, int option_name,
const void *option_value, socklen_t option_len);

功能:  用来设置套接字选项

参数:
socket   对哪一个套接字描述符进行设置
level    对哪一个层次进行设置(应用层、网络层、传输层)

1)SOL_SOCKET:通用套接字选项.
2)IPPROTO_IP:IP选项.
3)IPPROTO_TCP:TCP选项.
option_name   指定对应选项操作,具体查看手册
man  3 setsockopt
SO_RCVTIMEO   超时检测的选项

SO_SNDBUF     发送缓冲区大小
SO_RCVBUF     接收缓冲区大小
SO_BROADCAST  设置广播方式
。。。
option_value     设置对应的option_name的值是多少?
时间值得一个结构体
struct timeval {
__kernel_time_t     tv_sec;     /* seconds  秒数 */
__kernel_suseconds_t    tv_usec;    /* microseconds 微秒数*/
};
【注意】这两个值必须同时设置
option_len   是用来设定option_value这个指针变量所指向的变量的大小是多少?
option_len = sizeof(struct timeval)


通过select函数检测描述符

【注意】select设置的时间值只能一次有效,如果想要长期有效,必须经过多次设置

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
功能:  使用select检测多路文件描述符,条件满足立刻返回,否则阻塞
参数:
nfds   获取的有效的最大描述符  加  1
readfds   读描述符集合(里面存放的是可以读入数据的描述符)
fd_set里面是一个数组,用来存放描述符

writefds  写描述符集合
exceptfds 异常描述符集合
timeout   延时
struct timespec {
long    tv_sec;         /* seconds      设置秒数 */
long    tv_nsec;        /* nanoseconds  设置微妙数 */
};
【注意】两者必须同时设置,才能生效
返回值:
成功  返回有效描述符的个数
失败  -1


通过alarm函数并处理SIGALRM信号

这里涉及到信号的一个使用技巧。因为设置信号处理函数之后,当信号到来的时候,实际上是以中断的方式进入信号处理函数执行操作。如果信号到来的时候有一个函数调用处于阻塞状态,默认情况下执行完信号处理函数会回到阻塞状态,但是通过设置相应的参数,可以实现这样的效果:用alarm函数定时发送一个SIGALARM信号,执行完信号处理函数之后,原来的阻塞状态会被打破,同时返回一个EINTR错误码,然后我们在阻塞函数的后面检测这个错误码就可以实现超时检测功能。

【注意】alarm设置的时间值只能一次有效,如果想要长期有效,必须经过多次设置

int sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);

功能:  信号处理函数
参数:
signum  向内核注册的信号
act     设置信号信息
struct sigaction {
void     (*sa_handler)(int);  //信号处理函数
void     (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t   sa_mask;
int        sa_flags;          //信号标志位
SA_RESATRT   自动重启属性
(本身信号的SIGALRM默认操作是结束进程,但是改变信号的属性之后,让程序重新回到系统调用中断 的地方accept 、 recv)
void     (*sa_restorer)(void);
};

oldact  获取信号信息

sigaction() returns 0 on success and -1 on error
成功   0
失败  -1

sigaction使用原则:
1、获取信息
2、修改信息
3、重新设置信息
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息