linux网路编程--网络超时检测

Posted sucfrperperseverance

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux网路编程--网络超时检测相关的知识,希望对你有一定的参考价值。

网络超时检测(1)

  设置socket的属性SO_RCVTIMEO

参考代码:

struct timeval tv;

tv..tv_sec=5;//设置5s时间

tv.tv_usec=0;

setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv));//设置接收超时

recv/recvfrom

网络超时检查(2)

  用select检测socket是否‘ready’

参考代码:

struct fd_set rdfds;

struct timeval tv={5,0};

FD_ZERO(&rdfds);

FD_SET(sockfd,&rdfds);

if(selecet(sockfd+1,&rdfs,NULL,NULL,&tv)>0)//socket准备就绪

{

  recv/recvfrom

}

 

selct-timeout.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>

#define  N  128
#define err_log(errlog) do{perror(errlog);exit(1);}while(0)

int main(int argc, const char *argv[])
{
    fd_set readfds;
    int maxfd;
    int i = 0;
    char buf[N] = {};
    int ret;

    int sockfd;
    int acceptfd;
    struct sockaddr_in serveraddr, clientaddr;
    socklen_t addrlen = sizeof(clientaddr);

    if(argc < 3)
    {
        fprintf(stderr, "Usage:%s serverip port.\\n", argv[0]);
    }
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        err_log("fail to socket");
    }

    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
    serveraddr.sin_port = htons(atoi(argv[2]));

    if(bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
    {
        err_log("fail to bind");
    }

    if(listen(sockfd, 5) < 0)
    {
        err_log("fail to listen");
    }

    FD_ZERO(&readfds);
    maxfd = sockfd;

    struct timeval tv;

    while(1)
    {
        FD_SET(0, &readfds);
        FD_SET(sockfd, &readfds);

        tv.tv_sec = 5;
        tv.tv_usec = 0;

        if((ret = select(maxfd+1,&readfds, NULL, NULL,&tv)) < 0)
        {
            err_log("fail to select");
        }
        printf("After select.\\n");

        switch(ret)
        {
        case 0:
            printf("Timeout....\\n");
            break;
        default :
            for(i = 0; i < maxfd+1; i++)
            {
                if(FD_ISSET(i, &readfds))
                {
                    if(i == 0)
                    {
                        fgets(buf, N, stdin);
                        printf("buf:%s", buf);
                    }
                    if(i == sockfd)
                    {
                        if((acceptfd = accept(sockfd, (struct sockaddr*)&clientaddr, &addrlen)) < 0)
                        {
                            err_log("fail to accept");
                        }
                        printf("%s --> %d --> acceptfd = %d\\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port), acceptfd);
                    }

                }
            } // end default
        } // endswitch
    }
    
    return 0;
}

 

网络超时(3)

设置定时器(timer),捕捉SIGALRM信号

参考代码:

  void handler(int signo){return;}

//一旦进程收到这个信号,执行完信号处理函数之后,下一个函数就会直接返回,不阻塞在哪里

struct sigaction act;

sigaction(SIGALRM,NULL,&act);

act.sa_handler=handler

act.sa_flag&=~SA_RESTART;

sigaction(SIGALRM,&act,NULL);

alarm(5)

if(recv(...)<0)....

 

server-alarm.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <errno.h>

#define  err_log(errlog)  do{perror(errlog); exit(1);}while(0)
#define  N  128

// ./server  192.168.0.196  10000

void handler(int sig)
{
    printf("timeout....\\n");
}

int main(int argc, const char *argv[])
{
    int sockfd;
    int confd;
    struct sockaddr_in  serveraddr, clientaddr;
    char buf[N] = {};

    if(argc != 3)
    {
        fprintf(stderr, "Usage:%s serverip port.\\n", argv[0]);
        return -1;
    }

    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        err_log("fail to socket");
    }

    printf("sockfd = %d\\n", sockfd);

    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
    serveraddr.sin_port = htons(atoi(argv[2]));

    if(bind(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
    {
        err_log("fail to bind");
    }

    if(listen(sockfd, 10) < 0)
    {
        err_log("fail to listen");
    }

    socklen_t addrlen = sizeof(struct sockaddr);
    if((confd = accept(sockfd, (struct sockaddr *)&clientaddr, &addrlen)) < 0)
    {
        err_log("fail to accept");
    }

    printf("confd = %d , %s --> %d \\n", confd , inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
    
    struct sigaction act;

    sigaction(SIGALRM, NULL, &act);

    act.sa_handler = handler;
    act.sa_flags &= ~SA_RESTART;

    sigaction(SIGALRM, &act, NULL);


    while(1)
    {
        alarm(5);
        if(recv(confd, buf, N, 0) < 0)
        {
            if(errno == 4)
            {
                printf("errno = %d\\n", errno);
            }
            else
            {
                err_log("fail to recv");
            }
        }
        printf("From client:%s\\n", buf);

    }

    close(sockfd);

    return 0;
}

 

编译运行,如果客户端5秒不输入,则可以看到

 

以上是关于linux网路编程--网络超时检测的主要内容,如果未能解决你的问题,请参考以下文章

Linux系统状态检测

使用 Pygments 检测代码片段的编程语言

linux网络编程中的超时设置

Linux下怎么检测网络的连通状态

Socket网络编程

网路编程