zoukankan      html  css  js  c++  java
  • SO_LINGER RST linger

    如果我们在调用accept函数返回之前, 该客户端TCP发送了一个RST(复位)。在服务器中, 表现为该连接仍在TCP队列中, 等待服务器进程调用accept的时候RST到达。此时返回的套接字是一个已连接,但是却有接受了RST的套接字。

    模型图如下:

     

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <string.h>
    #include <ctype.h>
    #include <errno.h>
    #include <arpa/inet.h>
    
    #define SERV_PORT 10001
    #define SERV_IP "0.0.0.0"
    
    int main(void) {
        int sfd, cfd;
        int len, i;
        //BUFSIZ是系统内嵌的一个宏,用来指定buf大小
        char buf[BUFSIZ], clie_IP[BUFSIZ];
        struct sockaddr_in serv_addr, clie_addr;
        socklen_t clie_addr_len;
        sfd = socket(AF_INET, SOCK_STREAM, 0);
        bzero(&serv_addr, sizeof(serv_addr));      
        serv_addr.sin_family = AF_INET;           
        inet_pton(AF_INET , SERV_IP , &serv_addr.sin_addr.s_addr);
        serv_addr.sin_port = htons(SERV_PORT);              
    
        //绑定套接字
        bind(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
        listen(sfd, 64);
        printf("wait for client connect ...
    ");
        clie_addr_len = sizeof(clie_addr);
        while(1)
        {   
            //在accept之前休眠10s
            sleep(10);
    
            //阻塞等待客户端发起连接
            cfd = accept(sfd, (struct sockaddr *)&clie_addr, &clie_addr_len);
            //打印accept后的信息和客户端的连接
            if(cfd > 0) {
                printf("accept cfd = %d
    " , cfd);
            }
    
            printf("client IP:%s	port:%d
    ", 
                inet_ntop(AF_INET, &clie_addr.sin_addr.s_addr, clie_IP, sizeof(clie_IP)), 
                ntohs(clie_addr.sin_port));
    
            //服务端读取数据
            len = read(cfd, buf, sizeof(buf));
            //read返回0说明对端已经关闭
            if(len < 0) {
                //进一步判断是否收到RST
                if(errno == ECONNRESET) {
                    printf("read reset by peer
    ");
                    break;
                }
            }
        }
        close(sfd);
        close(cfd);
        return 0;
    }
    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <errno.h>
    
    #define SERV_IP "127.0.0.1"
    #define SERV_PORT 10001
    
    int main(void) {
        int sfd, len,ret;
        struct sockaddr_in serv_addr;
        struct linger lgr;
        char buf[BUFSIZ];
    
        sfd = socket(AF_INET, SOCK_STREAM, 0);
        if(ret < 0){
            perror("set SO_LINGER Error");
        }
    
        bzero(&serv_addr, sizeof(serv_addr));                       
        serv_addr.sin_family = AF_INET;                         
        inet_pton(AF_INET, SERV_IP, &serv_addr.sin_addr.s_addr); 
        serv_addr.sin_port = htons(SERV_PORT);                      
    
        //客户端connect连接返回,通过SO_LINGER选项立刻发送RST
        lgr.l_onoff = 1;
        lgr.l_linger = 0;
        ret = setsockopt(sfd, SOL_SOCKET, SO_LINGER, &lgr, sizeof lgr);
    
        ret = connect(sfd, (struct sockaddr *)&serv_addr ,  sizeof(serv_addr));
        if(ret == 0)
        {
            printf("client connect successful
    ");
        }
    
        //关闭链接
        close(sfd);
        return 0;
    }

     RST报文

    demo2

    服务端不变

    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <errno.h>
    
    #define SERV_IP "127.0.0.1"
    #define SERV_PORT 10001
    
    int main(void) {
        int sfd, len,ret;
        struct sockaddr_in serv_addr;
        struct linger lgr;
        char buf[BUFSIZ];
    
        sfd = socket(AF_INET, SOCK_STREAM, 0);
        if(ret < 0){
            perror("set SO_LINGER Error");
        }
    
        bzero(&serv_addr, sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        inet_pton(AF_INET, SERV_IP, &serv_addr.sin_addr.s_addr);
        serv_addr.sin_port = htons(SERV_PORT);
    
        //客户端connect连接返回,通过SO_LINGER选项立刻发送RST
        lgr.l_onoff = 1;
        lgr.l_linger = 10; 
        ret = setsockopt(sfd, SOL_SOCKET, SO_LINGER, &lgr, sizeof lgr);
    
        ret = connect(sfd, (struct sockaddr *)&serv_addr ,  sizeof(serv_addr));
        if(ret == 0)
        {
            printf("client connect successful
    ");
        }
    
        //关闭链接
        close(sfd);
        return 0;
    }

     

    更改l_linger 

    //客户端connect连接返回,通过SO_LINGER选项立刻发送RST
        lgr.l_onoff = 1;
        lgr.l_linger = 1;
        ret = setsockopt(sfd, SOL_SOCKET, SO_LINGER, &lgr, sizeof lgr);

    demo3

    //客户端connect连接返回,通过SO_LINGER选项立刻发送RST
        lgr.l_onoff = 0;
        lgr.l_linger = 1;
        ret = setsockopt(sfd, SOL_SOCKET, SO_LINGER, &lgr, sizeof lgr);

    demo4

    int main(void) {
        int sfd, len,ret;
        struct sockaddr_in serv_addr;
        struct linger lgr;
        char buf[BUFSIZ];
    
        sfd = socket(AF_INET, SOCK_STREAM, 0);
        if(ret < 0){
            perror("set SO_LINGER Error");
        }
    
        bzero(&serv_addr, sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        inet_pton(AF_INET, SERV_IP, &serv_addr.sin_addr.s_addr);
        serv_addr.sin_port = htons(SERV_PORT);
    
        //客户端connect连接返回,通过SO_LINGER选项立刻发送RST
        lgr.l_onoff = 1;
        lgr.l_linger = 10;
        ret = setsockopt(sfd, SOL_SOCKET, SO_LINGER, &lgr, sizeof lgr);
    
        ret = connect(sfd, (struct sockaddr *)&serv_addr ,  sizeof(serv_addr));
        if(ret == 0)
        {
            printf("client connect successful
    ");
        }
    
        //关闭链接
        close(sfd);
        write(sfd, "hello", sizeof("hello"));
        return 0;
    }

    TCP异常处理(accept返回前连接中止)与SO_LINGER选项

  • 相关阅读:
    linux freopen函数
    进程的环境变量environ
    ls -l 和du 的区别
    Python时间,日期,时间戳之间转换
    Web 服务器压力测试实例详解
    装numpy 环境:python3.4+ windows7 +64位系统
    在Windows Python3.4 上安装NumPy、Matplotlib、SciPy和IPython
    apache 自带的ab.exe 测试网站的并发量(网站压力测试)
    成员如何关注微信企业号?
    微信企业号通讯录有什么用?
  • 原文地址:https://www.cnblogs.com/dream397/p/14686217.html
Copyright © 2011-2022 走看看