2015-01-24 2 views
6

Durante la lettura di this great answer ho appreso che un socket TCP può avere uno stato chiamato TIME_WAIT. A causa di tale stato, è possibile che il socket TCP non abbia rilasciato l'indirizzo a cui è stato collegato, anche se la funzione close(int fd) ha restituito 0.Per i socket UDP, l'indirizzo IP non è limitato al momento in cui si chiude close()?

Dato che UDP è senza connessione e non hanno requisiti di affidabilità per fornire i dati, come TCP, è lecito ritenere che una volta che i rendimenti close(int fd)0, l'indirizzo è non legato?

risposta

6

Sì, in base al codice sorgente https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/udp.c?id=refs/tags/v3.19-rc6, udp_destroy_sock() (~ line 2028) elimina qualsiasi frame in sospeso e rilascia il socket che libera l'indirizzo.

È possibile dimostrarlo con un semplice esempio. Avrai bisogno di netcat, un client e un server. Un server, eseguire questo codice:

#include <arpa/inet.h> 
#include <netinet/in.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <stdio.h> 
#include <string.h> 
int main() { 
    struct sockaddr_in me; 
    int sock; 

    if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { 
     perror("socket error:"); 
     return -1; 
     } 
    memset(&me, 0, sizeof(me)); 
    me.sin_family = AF_INET; 
    me.sin_port = htons(60000); 
    me.sin_addr.s_addr = htonl(INADDR_ANY); 
    if (bind(sock, (struct sockaddr*)&me, sizeof(me)) == -1) { 
     perror("bind error: "); 
     return -1; 
     } 

    printf("On client execute:\n"); 
    printf("  nc -u {servers ip address} 60000\n\n"); 
    printf("type: hello world<enter>\n"); 
    printf("Hit enter when you've done this..."); 
    getchar(); 

    printf("\nNow check the input queue on this server\n"); 
    printf(" netstat -an|grep 60000\n"); 
    printf("Notice that we have buffered data we have not read\n"); 
    printf("(probably about 360 bytes)\n"); 
    printf("Hit enter to continue..."); 
    getchar(); 

    printf("\nI'm going to end. After I do, run netstat -an again\n"); 
    printf("and you'll notice port 60000 is gone.\n\n"); 
    printf("Re-run this program on server again and see you\n"); 
    printf("have no problem re-acquiring the UDP port.\n"); 
    return 0; 
    } 
+0

Puoi aggiungere un esempio di codice (che può essere eseguito) come mostra che uno scenario in cui TCP non rilascia l'indirizzo su socket chiuso mentre UDP lo farebbe? – TheMeaningfulEngineer

+0

Penso che sia inutile mostrare lo stato TIME_WAIT di un socket TCP poiché è uno stato richiesto dalle specifiche, è documentato praticamente ovunque e il kernel di Linux include parametri sintonizzabili per influenzare la sua durata. Un socket entra sempre nello stato TIME_WAIT quando viene terminato normalmente. –

+0

Penso che l'OP stava cercando di confermare che una porta UDP è stata completamente rilasciata al termine del processo dell'acquirente. Sono d'accordo sul fatto che il riferimento al kernel di linux era la risposta autorevole, ma lui cercava un po 'più di fiducia in ciò che era vero - un modo per testare. – user590028

1

TL; DR: socket UDP saranno chiuse e non legato immediatamente (a meno che il suo un/indirizzo multicast di broadcast con altri ascoltatori).

TIME WAIT è specificato dall'originale RFC 793e si applica solo al TCP. Richiede una durata massima del segmento 2 * per scadere prima di chiudere il socket in TCP.

Il famoso Unix Network Programming di Stevens spiega anche TIME ATTESA del TCP in modo più dettagliato per i curiosi.

UDP non ha connessioni .. TIME WAIT non fa parte di quel protocollo.

La fonte di Linux, sebbene rilevante per il comportamento potenzialmente proprietario sui sistemi basati su Linux, non è l'autorità su tali argomenti.

L'originale 1981 Darpa TCP RFC 793 è autorevole, nonche la Berkeley Sockets api su cui sono basati POSIX sockets definire il comportamento previsto della socket API.

Altrettanto rilevante è il BSD network stack che alimentava il protocollo TCP/IP nelle prime fasi di connessione a Windows, iOS e OSX e fornisce l'implementazione autorevole di riferimento delle RFC TCP/IP. Lo stack BSD è ancora considerato come the benchmark for a future Linux stack several years from now. (Facebook ha pubblicato un ruolo a metà del 2014 per un esperto per aiutare a fare coincidere Linux o superare l'affidabilità e le prestazioni dello stack FreeBSD).

Problemi correlati