2015-01-24 5 views
6

Während this great answer Lesen habe ich gelernt, dass ein TCP-Socket einen Zustand TIME_WAIT genannt haben. Wegen diesem Zustand ist es möglich, dass die TCP-Socket die Adresse nicht freigegeben hat es gebunden wurde, obwohl die close(int fd) Funktion 0 zurückgegeben.Für UDP-Sockets, ist die IP-Adresse unbeschränkt, wenn der Befehl close() zurückkehrt?

Vorausgesetzt, dass UDP verbindungslos ist und keine Zuverlässigkeitsanforderungen für die Übertragung der Daten wie TCP aufweist, kann davon ausgegangen werden, dass die Adresse close(int fd) zurückgibt, die Adresse nicht gebunden ist?

Antwort

6

Ja, entsprechend dem Quellcode 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() (~ Zeile 2028) löscht alle ausstehenden Frames und gibt den Socket frei, der die Adresse freigibt.

Sie können dies mit einem einfachen Beispiel demonstrieren. Sie benötigen netcat, einen Client und einen Server. Eine der Server, führen Sie diesen Code:

#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

Können Sie ein Codebeispiel hinzufügen (das ausgeführt werden kann), wie es zeigt, dass ein Szenario, in dem TCP die Adresse am Socket nicht freigeben würde, während UDP würde? – TheMeaningfulEngineer

+0

Ich denke, es ist unnötig, den TIME_WAIT-Status eines TCP-Sockels zu präsentieren, da es ein von den Spezifikationen vorgeschriebener Status ist, der überall ziemlich dokumentiert ist und der Linux-Kernel enthält einstellbare Parameter, um die Dauer zu beeinflussen. Ein Socket tritt immer in den Zustand TIME_WAIT ein, wenn er normal beendet wird. –

+0

Ich glaube, das OP versuchte zu bestätigen, dass ein UDP-Port vollständig freigegeben wurde, als der Acquirer-Prozess endete. Ich stimme zu, dass die Linux-Kernel-Referenz die maßgebliche Antwort war, aber er war auf der Suche nach ein wenig mehr Vertrauen, dass dies wahr war - eine Möglichkeit zu testen. – user590028

1

TL; DR: UDP-Sockets geschlossen und ungebundenen sofort (es sei denn, es ist ein Broadcast/Multicast-Adresse mit anderen Hörern).

TIME WAIT wird durch das Original RFC 793angegeben und gilt nur für TCP. Es erfordert eine 2-fache maximale Segmentlebensdauer, bevor der Socket in TCP geschlossen wird.

Die berühmten Unix Network Programming von Stevens erklärt auch für Neugierige im Detail TIME WAIT TCP.

UDP haben keine Verbindungen .. TIME WAIT nicht Teil des Protokolls ist.

Die Linux-Quelle, obwohl relevant für potenziell proprietäres Verhalten auf Linux-basierten Systemen ist nicht die Autorität in solchen Fragen.

Die ursprüngliche 1981 DARPA TCP RFC 793 ist autoritativ sowie die Berkeley Sockets api auf denen POSIX sockets basieren das erwartete Verhalten der Sockets API definieren.

Ebenfalls relevant ist die BSD network stack, die TCP/IP im frühen Internet bis hin zu Windows, iOS und OSX heute betrieben und die maßgebliche Referenzimplementierung der TCP/IP-RFCs bietet. Der BSD-Stack wird immer noch als the benchmark for a future Linux stack several years from now. angesehen (Facebook hat Mitte 2014 eine Rolle für einen Experten veröffentlicht, der dazu beitragen soll, dass Linux die Zuverlässigkeit und Leistung des FreeBSD-Stacks erreicht oder übertrifft).

Verwandte Themen