2016-07-21 8 views
1

Zurücksetzen eines accept Ed-Sockets in Anwendungsebene entweder mit IO :: Socket :: INET in Perl oder in C?Zurücksetzen einer TCP-Socket-Verbindung von der Anwendung

Es ist ein Programm bind ing, listen auf einem TCP-Port ing und accept s eine Client-Verbindung, nach, dass es read s und write einige Daten s. Wenn ich einfach close oder shutdown den Socket, TCP-Schicht würde ordnungsgemäß beendet (mit FIN-Paket), anstatt, würde ich ein RST-Paket generieren.

+0

AFAIK, es gibt keine Möglichkeit, dies mit dem Socket zu tun, den Sie gesendet und empfangen haben. Du könntest immer dein eigenes RST-Paket herstellen und es an deinen Partner schicken, aber du müsstest einen separaten rohen Paket-Socket erstellen, um es zu senden. Linux hat auch eine "SOCK_DESTROY" -Funktion (bedingt im Kernel enthalten), die von einem entsprechend privilegierten Prozess verwendet werden kann, um eine beliebige Verbindung zu schließen, aber es ist auch völlig out-of-band von Ihrem Anwendungs-Socket. Warum möchten Sie trotzdem mit RST terminieren? –

+2

Sie können versuchen, SO_LINGER Socket-Option mit Null-Timeout, [nach einigen Ressourcen] (http://stackoverflow.com/questions/3757289/tcp-option-so-linger-zero-when-its-required) wird es RST generieren Paket statt FIN. –

+0

@SlavaBacherikov danke, es funktioniert in Code: '$ Socket = IO :: Socket :: INET-> neu (Listen = 1, ReuseAddr => 1, LocalPort => ..., ...); $ client = $ socket-> accept(); $ client-> sockopt (SO_LINGER, pack ('II', 1, 0)); Schließen Sie $ client'. curl und wget behandeln diese Bedingung immer mit Rückgabecode 56 bzw. 4. netcat erkennt jedoch nichtdeterministisch irgendwann "Verbindung wird von Peer abgelehnt", aber manchmal nicht. – bandie

Antwort

1

Sie haben nicht das genaue Betriebssystem angegeben, das Sie verwenden. Ich habe herausgefunden, dass Linux einen API-Aufruf hat, der eine TCP-Verbindung zurücksetzt, ich habe keine Ahnung, wie portabel es ist. Der Weg dazu besteht darin, den Systemaufruf connect auf dem bereits verbundenen Socket zu verwenden, diesmal jedoch mit der Familie AF_UNSPEC.

Nachdem Sie einen Socket auf diese Weise zurückgesetzt haben, ist es sogar möglich, den Socket erneut mit einem anderen connect Aufruf zu verbinden.

int main(int argc, char** argv) 
{ 
    int fd = socket(AF_INET6, SOCK_STREAM, 0); 

    while (1) { 
    struct sockaddr_in6 sockaddr = { 
     .sin6_family = AF_INET6, 
     .sin6_port = htons(80), 
     .sin6_flowinfo = 0, 
     .sin6_scope_id = 0, 
    }; 
    struct timespec s = { 
     .tv_sec = 2, 
     .tv_nsec = 0, 
    }; 

    /* Connect to port 80 on localhost */ 
    inet_pton(AF_INET6, "::1", &sockaddr.sin6_addr.s6_addr); 
    connect(fd, (struct sockaddr*)&sockaddr,sizeof(sockaddr)); 
    nanosleep(&s, NULL); 

    /* Reset previously connected socket */ 
    sockaddr.sin6_family = AF_UNSPEC; 
    connect(fd, (struct sockaddr*)&sockaddr,sizeof(sockaddr)); 
    nanosleep(&s, NULL); 
    } 
} 
+0

großartig. Ich habe Ihre 'connect AF_UNSPEC'-Lösung auch auf dem ipv4-Hörszenario getestet, in diesem Fall muss ich nicht den' listen'-Anschluss neu verbinden, sondern den von 'accept' zurückgegebenen. – bandie

Verwandte Themen