2009-04-12 14 views
8

Próbowałem następujące:listen() bez wywoływania bind()

int sockfd = socket(...); 
listen(sockfd, 10); 
accept(sockfd, ...); 

Żadne z połączeń nie powiodła się, a program się rozpoczął blokowanie jakbym nazywa bind(). Co się stanie w tym przypadku? Czy nie będzie możliwe uzyskanie połączenia, ponieważ nie ma on lokalnego adresu lub portu? Czy też został domyślnie przypisany lokalny adres i port, a teraz słucha się ich? Jeśli tak, to w jaki sposób mogę je odzyskać?

Odpowiedz

10

Połączenia działają, ale ponieważ nie wiązałeś jawnie gniazda, system operacyjny lub biblioteka systemowa niejawnie przypisały port i domyślne powiązanie (dokładnie tak samo, jak po wywołaniu connect(2) bez wywoływania najpierw bind(2)). Ponadto, ponieważ wcześniej pytałeś o rzeczy związane z TCP, zakładam, że mówisz tutaj o gniazdach internetowych.

Dowiedz się, jaka nazwa systemu operacyjnego jest związana z różnymi systemami operacyjnymi, więc będziesz musiał szukać konkretnego systemu operacyjnego, ale większość systemów operacyjnych zapewnia netstat lub podobne narzędzie, które można wykorzystać do sprawdzenia, które aplikacje słuchają na których portach.,

Jak wspomina John w komentarzu, można użyć getsockname(2), aby znaleźć nazwę związanego gniazda. Oto krótki przykład:

// ... 

// Create socket and set it to listen (we ignore error handling for brevity) 
int sock = socket(AF_INET, SOCK_STREAM, 0); 
listen(sock, 10); 

// Sometime later we want to know what port and IP our socket is listening on 
socklen_t addr_size = sizeof(struct sockaddr_in); 
struck sockaddr_in addr; 
getsockname(sock, (struct sockaddr *)&addr, &addr_size); 

addr będzie teraz zawierać adres IP i numer portu, że gniazdo nasłuchuje.

+0

Wywołanie getsockname() daje adres/port przypisany przez system operacyjny. –

+0

Dobrze, John ... Dodam przykładowy kod. –

0

Podejrzewam, że nigdy nie uzyskasz połączenia. Możesz sprawdzić, czy jest nowe nasłuchiwanie, wykonując równoważnik "netstat -an" w twoim systemie operacyjnym przed i po uruchomieniu programu.

Próbowałem to samo w C#:

Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
socket.Listen(1); 
socket.Accept(); 

uzyskać wyjątek w drugim wierszu, który informuje mnie w okrężny sposób, że wymagane jest Bind. To oczywiście działa dobrze z:

Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
socket.Bind(new IPEndPoint(IPAddress.Loopback, 4567)); 
socket.Listen(1); 
socket.Accept(); 

testowałem z gniazda UDP, jak również i to samo, Windows nie jest szczęśliwy na Sluchaj nazwać chyba Wiązanie zostało zrobione. Ponieważ wywołania gniazd .Net są po prostu wrappers wokół Winsock, zachowanie to prawdopodobnie będzie takie samo dla wszystkich bibliotek pochodnych Winsock w systemie Windows.

2

Jak wspomnieli inni, system operacyjny przydzieli port, jeśli nie zostanie powiązany(). Możesz użyć wywołania getsockname() po listen(), aby zobaczyć, jaki adres/port są przypisane. Następnie, jeśli przekażesz ten adres/port klientowi, może on się połączyć.

To ma sens, żeby to zadziałało. Możesz napisać program, w którym to było interesujące.

Powiązane problemy