在 centos 7 上同步确认后的插座鳍
socket fin after syn ack on centos 7
我用 epoll 写了一个 tcp 服务器,它在 Ubuntu 上运行正常,但在 CentOS7 上偶尔会发生奇怪的事情。
客户端a尝试连接到服务器b,连接已建立,
客户端端口为59298,服务器端口为8802,服务器端socketfd为16.
[同义词]
[同步、确认]
[确认]
同时服务器读取 return 值为零的事件,具有相同的 sockfd,即 16,与之前的连接建立相同,告诉 a 和 b 之间的连接已关闭。服务器发送一个 [rst,ack] 包到不同端口的客户端,即 59191。为什么会这样?是centos内核的bug吗?
我的代码与下面的代码非常相似。
#define MAX_EVENTS 10
struct epoll_event ev, events[MAX_EVENTS];
int listen_sock, conn_sock, nfds, epollfd;
/* Set up listening socket, 'listen_sock' (socket(),
bind(), listen()) */
epollfd = epoll_create(10);
if (epollfd == -1) {
perror("epoll_create");
exit(EXIT_FAILURE);
}
ev.events = EPOLLIN;
ev.data.fd = listen_sock;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev) == -1) {
perror("epoll_ctl: listen_sock");
exit(EXIT_FAILURE);
}
for (;;) {
nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
if (nfds == -1) {
perror("epoll_pwait");
exit(EXIT_FAILURE);
}
for (n = 0; n < nfds; ++n) {
if (events[n].data.fd == listen_sock) {
conn_sock = accept(listen_sock,
(struct sockaddr *) &local, &addrlen);
if (conn_sock == -1) {
perror("accept");
exit(EXIT_FAILURE);
}
setnonblocking(conn_sock);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = conn_sock;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock,
&ev) == -1) {
perror("epoll_ctl: conn_sock");
exit(EXIT_FAILURE);
}
} else {
do_use_fd(events[n].data.fd);
}
}
}
这是我的 tcpdump 结果。
看了man epoll才知道原因。它是由于不合适的代码而发生的。
epoll_ctl(epollfd_, EPOLL_CTL_DEL, sockfd, &ev)
在github上似乎很少有关于epoll的正确使用示例。
我用 epoll 写了一个 tcp 服务器,它在 Ubuntu 上运行正常,但在 CentOS7 上偶尔会发生奇怪的事情。
客户端a尝试连接到服务器b,连接已建立, 客户端端口为59298,服务器端口为8802,服务器端socketfd为16.
[同义词]
[同步、确认]
[确认]
同时服务器读取 return 值为零的事件,具有相同的 sockfd,即 16,与之前的连接建立相同,告诉 a 和 b 之间的连接已关闭。服务器发送一个 [rst,ack] 包到不同端口的客户端,即 59191。为什么会这样?是centos内核的bug吗?
我的代码与下面的代码非常相似。
#define MAX_EVENTS 10
struct epoll_event ev, events[MAX_EVENTS];
int listen_sock, conn_sock, nfds, epollfd;
/* Set up listening socket, 'listen_sock' (socket(),
bind(), listen()) */
epollfd = epoll_create(10);
if (epollfd == -1) {
perror("epoll_create");
exit(EXIT_FAILURE);
}
ev.events = EPOLLIN;
ev.data.fd = listen_sock;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev) == -1) {
perror("epoll_ctl: listen_sock");
exit(EXIT_FAILURE);
}
for (;;) {
nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
if (nfds == -1) {
perror("epoll_pwait");
exit(EXIT_FAILURE);
}
for (n = 0; n < nfds; ++n) {
if (events[n].data.fd == listen_sock) {
conn_sock = accept(listen_sock,
(struct sockaddr *) &local, &addrlen);
if (conn_sock == -1) {
perror("accept");
exit(EXIT_FAILURE);
}
setnonblocking(conn_sock);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = conn_sock;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock,
&ev) == -1) {
perror("epoll_ctl: conn_sock");
exit(EXIT_FAILURE);
}
} else {
do_use_fd(events[n].data.fd);
}
}
}
这是我的 tcpdump 结果。
看了man epoll才知道原因。它是由于不合适的代码而发生的。
epoll_ctl(epollfd_, EPOLL_CTL_DEL, sockfd, &ev)
在github上似乎很少有关于epoll的正确使用示例。