我正在用套接字测试东西,遇到了一个奇怪的情况:
我用 C 语言编写了一个非常简单的 tcp 服务器,我让它在 accept() 之后阻塞,只是为了看看当同时接受多个连接尝试时会发生什么:
以下是服务器代码的摘录:
//listen()
if( (listen(sock,5)) == -1) {
perror("listen");
exit(-1);
}
//accept()
if( (cli = accept(sock, (struct sockaddr *) &client, &len)) == 1 ){
perror("accept");
exit(-1);
}
printf("entrez un int : ");
scanf("%d",&toto);
当服务器要求用户输入一个整数时,我尝试使用 telnet 连接多个客户端。
对于第一个,一切正常:
root@[...] :/home/[...]/workspace/sockets# netstat -antp | grep 10003
tcp 0 0 0.0.0.0:10003 0.0.0.0:* LISTEN 25832/toto
tcp 0 0 127.0.0.1:10003 127.0.0.1:51166 ESTABLISHED 25832/toto
tcp 0 0 127.0.0.1:51166 127.0.0.1:10003 ESTABLISHED 25845/telnet
但是在第一个之后,即使我是root,也有一些连接我看不到拥有它的进程和它的pid:
root@[...] :/home/[...]/workspace/sockets# netstat -antp | grep 10003
tcp 0 0 0.0.0.0:10003 0.0.0.0:* LISTEN 25832/toto
tcp 0 0 127.0.0.1:10003 127.0.0.1:51166 ESTABLISHED 25832/toto
tcp 0 0 127.0.0.1:51166 127.0.0.1:10003 ESTABLISHED 25845/telnet
tcp 0 0 127.0.0.1:10003 127.0.0.1:51168 ESTABLISHED -
tcp 0 0 127.0.0.1:51168 127.0.0.1:10003 ESTABLISHED 25852/telnet
第三个:
root@[...] :/home/[...]/workspace/sockets# netstat -antp | grep 10003
tcp 0 0 0.0.0.0:10003 0.0.0.0:* LISTEN 25832/toto
tcp 0 0 127.0.0.1:10003 127.0.0.1:51166 ESTABLISHED 25832/toto
tcp 0 0 127.0.0.1:51166 127.0.0.1:10003 ESTABLISHED 25845/telnet
tcp 0 0 127.0.0.1:10003 127.0.0.1:51172 ESTABLISHED -
tcp 0 0 127.0.0.1:10003 127.0.0.1:51168 ESTABLISHED -
tcp 0 0 127.0.0.1:51168 127.0.0.1:10003 ESTABLISHED 25852/telnet
tcp 0 0 127.0.0.1:51172 127.0.0.1:10003 ESTABLISHED 25860/telnet
几天后,我以 root 身份再次尝试使用 netstat -antpe,得到的结果如下:
root@[...] :/home/[...]/workspace/sockets# netstat -antpe | grep 10003
tcp 0 0 0.0.0.0:10003 0.0.0.0:* LISTEN 1000 327680 22399/toto
tcp 0 0 127.0.0.1:33286 127.0.0.1:10003 ESTABLISHED 1000 417202 22884/telnet
tcp 0 0 127.0.0.1:10003 127.0.0.1:33046 ESTABLISHED 0 0 -
tcp 0 0 127.0.0.1:10003 127.0.0.1:33286 ESTABLISHED 0 0 -
tcp 0 0 127.0.0.1:33044 127.0.0.1:10003 ESTABLISHED 1000 332810 22402/telnet
tcp 0 0 127.0.0.1:33046 127.0.0.1:10003 ESTABLISHED 1000 331200 22410/telnet
tcp 0 0 127.0.0.1:10003 127.0.0.1:33044 ESTABLISHED 1000 332801 22399/toto
为什么进程或连接的 inode 为 0?有人能解释一下发生了什么吗?
答案1
Linux 使用双队列方法来处理监听积压。这意味着,除了完全的连接(代码中为 5)可以有一个队列不完整连接,其中三次握手尚未完成。
处于此状态的连接尚未分配给进程,因此它们仅属于内核,因此进程 ID 为 0。这在 Mono/.NET 应用程序上困扰着我,我当时正在 Mono 中寻找一个错误,而这实际上是内核设计的行为。
看这里了解双队列方法的详细信息。