本文介绍了接受后配置TCP Keepalive的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在套接字上的 accept()之后,我正在尝试配置TCP keepalive.

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

SockConnected = accept(SockListen, &RemoteAddr,
                   &RemoteLen);
/* A bit of checking goes here */
if (setsockopt (SockConnected , SOL_SOCKET, SO_KEEPALIVE,
                            (ST_CHAR *) &sockopt_on, sizeof (int) ) )
{
   /* Error logging */
}

if (setsockopt(SockConnected , IPPROTO_TCP, TCP_KEEPIDLE, (char*)&(sockopt_tcp_keep_idle), sizeof(sockopt_tcp_keep_idle)))
{
    /* Error logging */
}
if (setsockopt(SockConnected, IPPROTO_TCP, TCP_KEEPINTVL, (char*)&(sockopt_tcp_keep_intvl), sizeof(sockopt_tcp_keep_intvl)))
{
    /* Error logging */
}
if (setsockopt(SockConnected, IPPROTO_TCP, TCP_KEEPCNT, (char*)&(sockopt_tcp_keep_cnt), sizeof(sockopt_tcp_keep_cnt)))
{
    /* Error logging */
}

为所有四个属性调用 getsockopt()之后,一切似乎都很好.我已经检查过Wireshark,并且没有正在发送的保持活动"数据包.我必须将 SOL_TCP 更改为 IPPROTO_TCP ,因为当为 TCP_KEEPIDLE 调用 setsockopt()时,它返回errno 92(未找到协议).

After calling getsockopt() for all four properties, everything seems alright. I've checked in Wireshark and there are no Keep alive packets being sent. I had to change SOL_TCP to IPPROTO_TCP, because when calling setsockopt() for TCP_KEEPIDLE it was returning errno 92 (Protocol not found).

在调用 socket()进行传出连接后,我正在做同样的事情,并且运行良好.

I'm doing the same thing after calling socket() for an outgoing connection, and it's working perfectly.

我正在使用C和Linux.

I'm using C and Linux.

在接受后,为什么 setsockopt 可能不起作用?

Is there any reason why setsockopt may not be working after an accept?

推荐答案

这是一个最小的工作示例.如果它适合您,您可以将其用作参考.

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;
}

示例输出( tcpdump 每秒报告一次保持活动的数据包):

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

这篇关于接受后配置TCP Keepalive的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-06 04:18