gpt4 book ai didi

linux - 在服务器中使用 TCP Keep-Alives 摆脱空闲客户端

转载 作者:可可西里 更新时间:2023-11-01 02:43:29 27 4
gpt4 key购买 nike

我有一个服务器来收集来自不同客户端的Tcp数据到某个端口。我有一个场景,每当客户端创建 tcp 连接并保持空闲状态超过假设 30 分钟 时,我就需要关闭连接。

我了解了TCP keep alive 以跟踪对等方是否已死,并且大多数情况下我发现了在客户端使用的示例。同样,我可以在服务器端使用来轮询连接是否处于事件状态吗?

此外,在 linux sysctl.conf 中,有一个配置文件可以编辑这些值。这似乎是整个 tcp 连接在某些不活动后被破坏。我需要在一段时间不活动后销毁设备的某些连接,但不会关闭整个 tcp 端口连接。

我正在使用 ubuntu 创建服务器来收集 TCP 连接。我可以在服务器代码中使用 TCP Keep-Alives 来查找非事件客户端并关闭特定客户端吗?还是在服务器端有其他方法来实现这种功能?

在浏览网页时提到

(getsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &optval, &optlen)

这个 getsockopt 是针对主 tcp 连接的,这里的设置似乎是针对与服务器的整个连接。

但是我需要的是特定客户。我有事件服务器代码作为这里 client_fd 被接受,如果在特定时间内未收到通过此客户端的下一个数据,现在我需要关闭此 client_fd。

void event_server(EV_P_ struct ev_io *w, int revents) {
int flags;
struct sockaddr_in6 addr;
socklen_t len = sizeof(addr);

int client_fd;

// since ev_io is the first member,
// watcher `w` has the address of the
// start of the _sock_ev_serv struct
struct _sock_ev_serv* server = (struct _sock_ev_serv*) w;
server->socket_len = len;

for (;;) {
if ((client_fd = accept(server->fd, (struct sockaddr*) &addr, &len)) < 0) {
switch (errno) {
case EINTR:
case EAGAIN:
break;
default:
zlog_info(_c, "Error accepting connection from client \n");
//perror("accept");
}
break;
}
char ip[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &addr.sin6_addr, ip, INET6_ADDRSTRLEN);
char *dev_ip = get_ip(ip);
server->device_ip = dev_ip;

zlog_debug(_c,"The obtained ip is %s and dev_ip is %s", ip, dev_ip);

/** check for the cidr address for config_ip **/
char *config_ip;
config_ip = get_config_ip(dev_ip, _client_map);
zlog_debug(_c,"The _config ip for dev_ip:%s is :%s", dev_ip, config_ip);
if (config_ip == NULL) {
zlog_debug(_c,"Connection attempted from unreigistered IP: %s", dev_ip);
zlog_info(_c, "Connection attempted from unregistered IP : %s", dev_ip);
AFREE(server->device_ip);
continue;
}

json_t *dev_config;
dev_config = get_json_object_from_json(_client_map, config_ip);
if (dev_config==NULL) {
zlog_debug(_c,"Connection attempted from unreigistered IP: %s", dev_ip);
zlog_info(_c, "Connection attempted from unregistered IP : %s", dev_ip);
AFREE(server->device_ip);
continue;
}

if ((flags = fcntl(client_fd, F_GETFL, 0)) < 0 || fcntl(client_fd, F_SETFL, flags | O_NONBLOCK) < 0) {
zlog_error(_c, "fcntl(2)");
}


struct _sock_ev_client* client = malloc(sizeof(struct _sock_ev_client));
client->device_ip = dev_ip;
client->server = server;
client->fd = client_fd;

// ev_io *watcher = (ev_io*)calloc(1, sizeof(ev_io));
ev_io_init(&client->io, event_client, client_fd, EV_READ);
ev_io_start(EV_DEFAULT, &client->io);
}
}

最佳答案

TCP keep alives 不是为了检测空闲客户端,而是为了检测死连接,即如果客户端在没有关闭连接的情况下崩溃,或者线路是否死机等。但是如果客户端只是空闲但没有死,连接仍然是打开的.任何向客户端发送空数据包(keep-alive 数据包)的尝试都会导致来自客户端的 ACK,因此 keep-alive 不会报告死连接。

要检测空闲客户端,请改为使用读取超时 (SO_RCVTIMEO) 或使用带有选择、轮询或类似功能的超时。

关于linux - 在服务器中使用 TCP Keep-Alives 摆脱空闲客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34461624/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com