套接字keepalive无法正常工作

时间:2014-02-18 23:24:16

标签: c++ linux sockets tcp

我有一个客户端connect()到服务器,当空闲时,它会在几个小时后超时。 我补充道 setsockopt(套接字,SOL_SOCKET,SO_KEEPALIVE ...),1秒 但它并没有什么不同。 为什么keepalive不起作用的任何线索? 如果我使用SOL_TCP而不是SOL_SOCKET会有所不同吗? 这是在Linux上。

2 个答案:

答案 0 :(得分:9)

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

只需启用Keepalive。您将获得keepalive探针的默认计时器,您可以使用以下命令查看:

sysctl net.ipv4.tcp_keepalive_time

通常默认值是几个小时。

如果您想更改默认计时器,可以使用:

struct KeepConfig cfg = { 60, 5, 5};
set_tcp_keepalive_cfg(fd, &cfg);

使用辅助函数:

struct KeepConfig {
    /** The time (in seconds) the connection needs to remain 
     * idle before TCP starts sending keepalive probes (TCP_KEEPIDLE socket option)
     */
    int keepidle;
    /** The maximum number of keepalive probes TCP should 
     * send before dropping the connection. (TCP_KEEPCNT socket option)
     */
    int keepcnt;

    /** The time (in seconds) between individual keepalive probes.
     *  (TCP_KEEPINTVL socket option)
     */
    int keepintvl;
};

/**
* enable TCP keepalive on the socket
* @param fd file descriptor
* @return 0 on success -1 on failure
*/
int set_tcp_keepalive(int sockfd)
{
    int optval = 1;

    return setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval));
}

/** Set the keepalive options on the socket
* This also enables TCP keepalive on the socket
*
* @param fd file descriptor
* @param fd file descriptor
* @return 0 on success -1 on failure
*/
int set_tcp_keepalive_cfg(int sockfd, const struct KeepConfig *cfg)
{
    int rc;

    //first turn on keepalive
    rc = set_tcp_keepalive(sockfd);
    if (rc != 0) {
        return rc;
    }

    //set the keepalive options
    rc = setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPCNT, &cfg->keepcnt, sizeof cfg->keepcnt);
    if (rc != 0) {
        return rc;
    }

    rc = setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, &cfg->keepidle, sizeof cfg->keepidle);
    if (rc != 0) {
        return rc;
    }

    rc = setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, &cfg->keepintvl, sizeof cfg->keepintvl);
    if (rc != 0) {
        return rc;
    }

    return 0;
}

答案 1 :(得分:2)

尽管名称不同,但keep-alive并不是要保持连接活动,而是定期交换数据包以确保对等体之间存在网络路径。它可以杀死在空闲时延长网络中断的连接。

由于这种行为,除非有充分的理由,例如telnet或SSH连接,否则不应使用keep-alive,在客户端失去联系时终止会话是合理的。

由于某些连接处理策略,很可能是服务器在n小时后关闭连接而不管keepalive使用情况。

相关问题