问题描述
在套接字上的 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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!