为何未调用accept()时telnet仍能与监听Socket建立连接?
问题:未调用accept()时telnet为何仍能建立连接?
以下是一段极简示例代码:
#include <errno.h> #include <string.h> #include <sys/types.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/tcp.h> #include <arpa/inet.h> #include <sys/epoll.h> #include <stdio.h> #include <stdlib.h> #define NPROTO 10000 #define LOCALHOST "127.0.0.1" int main(int argc, char *argv[]) { int sfd, epfd; struct sockaddr_in so_address; struct epoll_event ev, evs[1]; sfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); if(sfd < 0){ fprintf(stderr, "socket() failed\n"); exit(1); } epfd = epoll_create(1); if(epfd < 0){ fprintf(stderr, "epoll_create() failed\n"); exit(1); } memset(&so_address, 0, sizeof(so_address)); so_address.sin_family = AF_INET; so_address.sin_port = htons(NPROTO); if(1 != inet_pton(AF_INET, LOCALHOST, (struct in_addr*)(&so_address.sin_addr.s_addr))){ fprintf(stderr, "inet_pton() failed\n"); exit(1); } if(bind(sfd, (struct sockaddr *)&so_address, sizeof(so_address)) < 0){ fprintf(stderr, "bind() failed\n"); exit(1); } if(listen(sfd, 4) < 0){ fprintf(stderr, "listen() failed\n"); exit(1); } ev.data.fd = sfd; ev.events = 0; epoll_ctl(epfd, EPOLL_CTL_ADD, sfd, &ev); epoll_wait(epfd, evs, 1, -1); return 0; }
该代码创建用于监听连接的Socket,并将其注册到epoll集合中,最后等待epoll集合上的事件。
注意,struct epoll_event的events标志被设置为0。使用上述示例代码时,telnet可成功连接至程序;若将该标志改为EPOLLIN,telnet则会提示“Connection refused”。
问题解答
TCP连接的建立是内核层面完成三次握手,和用户态程序是否调用accept()没有直接关联:
当程序调用
listen(sfd, 4)后,内核会为这个监听Socket维护两个关键队列:- 半连接队列(SYN队列):存放已收到客户端SYN包、但还未完成三次握手的连接请求
- 全连接队列(Accept队列):存放已完成TCP三次握手、等待用户态调用
accept()取走的连接
当
telnet发起连接请求时,只要全连接队列还有空闲位置(示例中backlog参数设为4),内核就会自动完成TCP三次握手,把连接放入全连接队列。此时telnet会收到内核返回的连接成功响应,认为连接已建立——哪怕用户态程序完全没调用accept()去处理这个连接(只是后续无法传输数据,因为没有创建用于数据交互的Socket)。
两种场景的差异原因
- 当
ev.events = 0时:epoll_wait不会监听任何事件,进程会一直阻塞在这个调用上,监听Socket始终处于有效监听状态。此时telnet发起连接,内核完成三次握手后将连接放入全连接队列,telnet自然显示连接成功。 - 当
ev.events = EPOLLIN时:监听Socket的EPOLLIN事件会在全连接队列有新连接时触发,epoll_wait返回后程序直接退出,监听Socket被内核自动关闭。此时telnet发起连接时,目标端口已经没有进程在监听,因此会收到“Connection refused”的提示。
内容的提问来源于stack exchange,提问作者jorge is not ai
相关产品推荐
相关产品推荐

