【问题标题】:tcp keepalive - Protocol not available?tcp keepalive - 协议不可用?
【发布时间】:2018-11-22 20:50:39
【问题描述】:

我正在尝试设置 tcp keepalive,但这样做我看到了错误

“协议不可用”

int rc = setsockopt(s, SOL_SOCKET, TCP_KEEPIDLE, &keepalive_idle, sizeof(keepalive_idle));
if (rc < 0)
    printf("error setting keepalive_idle: %s\n", strerror(errno));

我可以打开keepalive,设置keepalive间隔和计数,但是keepalive idle(keepalive时间)会抛出该错误,我从来没有看到使用wireshark和过滤器tcp.analysis.keep_alive或使用任何keepalive数据包传输/接收tcpdump

sudo tcpdump -vv "tcp[tcpflags] == tcp-ack and less 1"

是否有需要加载的内核模块之类的?还是您不再能够覆盖全局 KEEPIDLE 时间。

顺便输出一下

matt@devpc:~/ sysctl net.ipv4.tcp_keepalive_time net.ipv4.tcp_keepalive_probes net.ipv4.tcp_keepalive_intvl
net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75

【问题讨论】:

  • tcp_keepalive_time 是发送第一个保活数据包之前的时间(以秒为单位)。根据您的示例,它设置为 2 小时。你真的等了那么久吗?减少并重试。
  • @KBart - 完全正确。这是默认设置。我想将其从默认值更改,但它给了我“协议不可用”。

标签: linux sockets tcp


【解决方案1】:

在我编写的应用程序中,以下工作:

setsockopt(*sfd, SOL_SOCKET, SO_KEEPALIVE,(char *)&enable_keepalive, sizeof(enable_keepalive));
setsockopt(*sfd, IPPROTO_TCP, TCP_KEEPCNT, (char *)&num_keepalive_strobes, sizeof(num_keepalive_strobes));
setsockopt(*sfd, IPPROTO_TCP, TCP_KEEPIDLE, (char *)&keepalive_idle_time_secs, sizeof(keepalive_idle_time_secs));
setsockopt(*sfd, IPPROTO_TCP, TCP_KEEPINTVL, (char *)&keepalive_strobe_interval_secs, sizeof(keepalive_strobe_interval_secs));

尝试将SOL_SOCKET 更改为IPPROTO_TCP 为TCPKEEPIDLE。

【讨论】:

  • 噢!谢谢帕布。我将 SOL_SOCKET 作为所有选项的第二个参数。它现在正在工作!
【解决方案2】:

有一个非常方便的库可以帮助你,它叫做 libkeepalive : http://libkeepalive.sourceforge.net/

它可以与LD_PRELOAD 一起使用,以便在所有 TCP 套接字上启用和控制保持活动状态。您还可以使用环境变量覆盖保持活动设置。

我尝试用它运行一个 tcp 服务器:

KEEPIDLE=5 KEEPINTVL=5 KEEPCNT=100 LD_PRELOAD=/usr/lib/libkeepalive.so nc -l -p 4242

然后我连接了一个客户端:

nc 127.0.0.1 4242

我使用 Wireshark 可视化流量:保持活动数据包恰好在 5 秒不活动后开始(我的系统范围设置为 75)。因此,这意味着可以覆盖系统设置。

这是libkeepalive 设置TCP_KEEPIDLE 的方式:

  if((env = getenv("KEEPIDLE")) && ((optval = atoi(env)) >= 0)) {
    setsockopt(s, SOL_TCP, TCP_KEEPIDLE, &optval, sizeof(optval));
  }

看起来他们使用SOL_TCP 而不是SOL_SOCKET。

【讨论】:

  • 无法使用。我不是在编写 GPL 代码,所以也无法链接到它。我只想拥有应该工作的东西,工作。
  • 好的,但我告诉过你,你的代码可能不起作用,因为你使用 SOL_SOCKET 而 libkeepalive 使用 SOL_TCP。
  • 欣赏这一点,但只需将 SOL_SOCKET 更改为 IPPROTO_TCP。固定。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-05
  • 1970-01-01
  • 2021-01-06
相关资源
最近更新 更多