Configuring TCP keepalive after accept

前端 未结 2 590
迷失自我
迷失自我 2021-02-05 21:53

After the accept() on a socket, I\'m trying to configure the TCP keepalive.

SockConnected = accept(SockListen, &RemoteAddr,
                   &         


        
相关标签:
2条回答
  • 2021-02-05 22:35

    SO_KEEPALIVE should be used with SOL_SOCKET, not IPPROTO_TCP or SOL_TCP. See socket(7) and tcp(7).

    So try this:

    int val = 1;
    setsockopt(SockConnected, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));
    

    I guess TCP_KEEPIDLE and similar options are just ignored if SO_KEEPALIVE was not set correctly, and SOL_TCP is a synonym for IPPROTO_TCP.

    If it does not help, consider posting a minimal example that reproduces the problem.

    0 讨论(0)
  • 2021-02-05 22:53

    Here is a minimal working example. If it works for you, you can use it as a reference.

    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <sys/signal.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <netinet/tcp.h>
    
    #define check(expr) if (!(expr)) { perror(#expr); kill(0, SIGTERM); }
    
    void enable_keepalive(int sock) {
        int yes = 1;
        check(setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(int)) != -1);
    
        int idle = 1;
        check(setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(int)) != -1);
    
        int interval = 1;
        check(setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(int)) != -1);
    
        int maxpkt = 10;
        check(setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &maxpkt, sizeof(int)) != -1);
    }
    
    int main(int argc, char** argv) {
        check(argc == 2);
    
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(12345);
        check(inet_pton(AF_INET, argv[1], &addr.sin_addr) != -1);
    
        int server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        check(server != -1);
    
        int yes = 1;
        check(setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != -1);
    
        check(bind(server, (struct sockaddr*)&addr, sizeof(addr)) != -1);
        check(listen(server, 1) != -1);
    
        if (fork() == 0) {
            int client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
            check(client != -1);
            check(connect(client, (struct sockaddr*)&addr, sizeof(addr)) != -1);
            printf("connected\n");
            pause();
        }
        else {
            int client = accept(server, NULL, NULL);
            check(client != -1);
            enable_keepalive(client);
            printf("accepted\n");
            wait(NULL);
        }
    
        return 0;
    }
    

    Example output (tcpdump reports keepalive packets every second):

    $ ./a.out 127.0.0.1 &
    [1] 14010
    connected
    accepted
    
    $ tcpdump -n -c4 -ilo port 12345
    dropped privs to tcpdump
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
    18:00:35.173892 IP 127.0.0.1.12345 > 127.0.0.1.60998: Flags [.], ack 510307430, win 342, options [nop,nop,TS val 389745775 ecr 389745675], length 0
    18:00:35.173903 IP 127.0.0.1.60998 > 127.0.0.1.12345: Flags [.], ack 1, win 342, options [nop,nop,TS val 389745775 ecr 389745075], length 0
    18:00:36.173886 IP 127.0.0.1.12345 > 127.0.0.1.60998: Flags [.], ack 1, win 342, options [nop,nop,TS val 389745875 ecr 389745775], length 0
    18:00:36.173898 IP 127.0.0.1.60998 > 127.0.0.1.12345: Flags [.], ack 1, win 342, options [nop,nop,TS val 389745875 ecr 389745075], length 0
    4 packets captured
    8 packets received by filter
    0 packets dropped by kernel
    
    0 讨论(0)
提交回复
热议问题