套接字超时接接收

一、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后,才进行应答处理
运行结果如下:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值