套接字超时接接收

来源:互联网 发布:淘宝佣金软件 编辑:程序博客网 时间:2024/06/06 05:34

一、SIGALRM超时超时接收问题

源代码片段:

#include "unp.h"/* *  recvfrom with a Timeout Using SIGALRM * */void sig_alrm(int signo){    fprintf(stdout,"SIGALRM is OK\n");    return;}void do_cli(FILE *fp, int sockfd,const struct sockaddr *pservaddr, socklen_t servlen){    int n;    char sendbuf[MAXLINE], recvbuf[MAXLINE];    socklen_t len;    while(Fgets(sendbuf, MAXLINE, fp) != NULL){        len = servlen;        Sendto(sockfd, sendbuf, strlen(sendbuf), 0, (struct sockaddr *) pservaddr, len);        Signal(SIGALRM, sig_alrm);        alarm(5);/*设置闹钟5s后, 将会产生SIGALRM信号,返回给系统*/        if((n = recvfrom(sockfd, recvbuf, MAXLINE, 0, NULL, NULL)) < 0){        if(errno == EINTR) fprintf(stderr, "socket timeout");/*因为系统调用而中断*/        else{            fprintf(stdout, "recvfrom error");        }        }else{            alarm(0);            recvbuf[n] = 0;     /* null terminate*/            Fputs(recvbuf, stdout);        }    }}
代码分析:

1-10:设置信号处理函数,已中断被堵赛的recvfrom函数

22-37:设置信号SIGALRM的处理函数, 用alarm设置一个5s超时。当recvfrom堵塞5s后, recvfrom函数将会被系统处理函数中断, 返回-1, 进入信号处理函数。处理完毕以后,系统将会,查看errno的值,分析recvfrom中断原因。

29-最后:alarm(0)关掉闹钟警报。


编译运行结果如下:




二、Select分析超时接收问题

代码片段如下:

#include "unp.h"/** * recvfrom with a Timeout Using select * */int read_timeio(int fd, int sec){    fd_set rset;    FD_ZERO(&rset);    struct timeval tv;    tv.tv_sec = sec;/*设置秒*/    tv.tv_usec = 0;/*毫秒设置为0*/    FD_SET(fd, &rset);    return Select(fd + 1, &rset, NULL, NULL, &tv);/*利用select函数最后一个参数的特性,计时扫描。当返回0的时候,代表超时返回*/}void do_cli(FILE *fp, int sockfd,const struct sockaddr *pservaddr, socklen_t servlen){    int n;    char sendbuf[MAXLINE], recvbuf[MAXLINE];    socklen_t len;    while(Fgets(sendbuf, MAXLINE, fp) != NULL){        len = servlen;        Sendto(sockfd, sendbuf, strlen(sendbuf), 0, (struct sockaddr *) pservaddr, len);        if(read_timeio(sockfd, 5) == 0){            fprintf(stderr, "socket timeout\n");        }else{            n = Recvfrom(sockfd, recvbuf, MAXLINE, 0, NULL, NULL);            recvbuf[n] = 0;            Fputs(recvbuf, stdout);        }    }}


服务端程序运行要求:通过睡眠5s后,才进行应答处理
运行结果如下:



三、SO_RCVTIMEO套接字设置超时接收问题

#include "unp.h"/* *  recvfrom with a Timeout Using SO_RCVTIMEO * */void do_cli(FILE *fp, int sockfd,const struct sockaddr *pservaddr, socklen_t servlen){    int n;    char sendbuf[MAXLINE], recvbuf[MAXLINE];    socklen_t len;    struct timeval tv;    tv.tv_sec = 5;    tv.tv_usec = 0;    Setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));    while(Fgets(sendbuf, MAXLINE, fp) != NULL){        len = servlen;        Sendto(sockfd, sendbuf, strlen(sendbuf), 0, (struct sockaddr *) pservaddr, len);        if((n = recvfrom(sockfd, recvbuf, MAXLINE, 0, NULL, NULL)) < 0){            if(errno == EWOULDBLOCK) fprintf(stderr, "socket timeout");            else{                fprintf(stdout, "recvfrom error");            }        }else{            recvbuf[n] = 0;     /* null terminate*/            Fputs(recvbuf, stdout);        }    }}
分析如下:

13-15:首先初始化结构timeval中的时间,因为该套接字对应的(SOL_SOCKET SO_RCVTIMEO)的结构是struct  timeval结构, 所以, 第四个参数的结构必须是struct timeval类型, 最后一个参数是 第四个参数的大小。

20-23:当io超时的时候, errno将会返回EWOULDBLOCK错误

服务端程序运行要求:通过睡眠5s后,才进行应答处理
运行结果如下:


原创粉丝点击