testuję rzeczy z gniazdami i napotkałem ten dziwny przypadek:
kodowałem bardzo prosty serwer tcp w c, zablokowałem go po accept (), aby zobaczyć, co się stanie, gdy przyjmuję wiele prób połączenia w tym samym czasie:
Oto fragment kodu serwera:
//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);
gdy serwer prosi użytkownika o wprowadzenie liczby całkowitej, próbuję połączyć wielu klientów za pomocą usługi telnet.
W pierwszym przypadku wszystko jest w porządku:
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
ale potem po pierwszym, mimo że jestem rootem, istnieją pewne połączenia, nie widzę procesu będącego jego właścicielem i jego 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
trzeci:
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
Próbowałem ponownie kilka dni później z netstat -antpe jako rootem i oto co mam:
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
dlaczego proces lub połączenie może mieć i-węzeł 0? Czy ktoś może mi wyjaśnić, co się dzieje?
Odpowiedzi:
Linux korzysta z dwóch kolejek do zaległości nasłuchu. Oznacza to, że oprócz kompletnych połączeń (5 jak w kodzie) może istnieć kolejka niekompletnych zatorów, w których uzgadnianie 3-kierunkowe nie zostało jeszcze zakończone.
Połączenia w tym stanie nie są jeszcze przypisane do procesu, więc należą do jądra, co skutkuje jedynie identyfikatorem procesu równym 0. To mnie ugryzło w aplikacji Mono / .NET, gdzie szukałem błędu w Mono, to znaczy faktycznie zachowanie zgodnie z projektem jądra.
Zobacz tutaj szczegóły podejścia do dwóch kolejek.
źródło