2012-09-04 11 views
7

Ich teste eine Client-Server-Kommunikation über einen TCP-Socket. Ich schrieb den Server in C und ich benutze es auf einem Linux-Rechner und ich verwende nc als Client für den Test.Gebrochenes Rohr nur beim zweiten Senden an einem geschlossenen Sockel

Der Server sendet nach einem initialen Austausch von Nachrichten mit dem Client einige Nachrichten periodisch an den Client, ohne eine Antwort zu erhalten.

Wenn ich den Client töten, erwarte ich, dass die erste send() vom Server erfolgt mit EPIPE Fehler fehlschlägt, aber dies stellt sich heraus, erst beim zweiten send() nachdem der Kunde gegangen ist! Die erste send() nach dem ich den Client getötet habe, kann erfolgreich 1100 Bytes an den (ich vermute, geschlossen) Socket senden. Der folgende send() Vorgang endet mit EPIPE wie angezeigt.

Gibt es jemanden, der mir dieses Verhalten erklären kann? Ist es aufgrund der Tatsache, dass ich auf den TCP/IP-Stack schreiben, so ist es an dem Stapel zu liefern, wenn es kann? Wenn ja, wie kann ich den Verbindungsstatus überprüfen? Um sicher zu sein, dass der Peer immer noch da ist.

Antwort

4

Normale TCP-Verbindung ist ein Vier-Wege-Handshake.

http://en.wikipedia.org/wiki/Transmission_Control_Protocol

Wenn Sie den Client das FIN Segment töten wird von der Clientseite auf den Server und den Server-Protokoll-Stack sendet die ACK gesendet.

Hier, wenn der Server versucht, Daten zu lesen, würde der gelesene Aufruf einen Wert von 0 zurückgeben, so dass Ihr Serverprogramm verstehen kann, dass der Peer geschlossen hat und normalerweise den Verbindungssockel danach schließen würde. Dies würde ermöglichen, dass die FIN von der Serverseite gesendet wird und der normale 4-Wege-Handshake nach dem Empfang der letzten ACK von der Client-Seite abgeschlossen wird.

(Pl lesen Q 2.1 von http://www.faqs.org/faqs/unix-faq/socket/)

Aber hier gibt es Daten vom Server schreiben, so dass der Server einen RESET vom Client nur Daten nach dem Senden erhält. So erhalten Sie den Fehler nach dem ersten Sendevorgang, der auf dem zweiten senden ist.

Also pl. versuchen Sie, die Verbindung von der Client-Seite abrupt anstelle von 4-Wege-Handsake, indem Sie die die Verweilzeit Option und Timeout auf 0, so dass Sie einen Fehler (kann anders sein als EPIPE) beim ersten Aufruf von senden auf die Server-Seite. (Dies ist keine recommnended Praxis aber nur für Ihr Verständnis in diesem speziellen Fall)

Try the following option of nc, nc -L 0 to set the linger option and timeout to 0 

(ich habe diese Option von nc nicht versucht, pl. prüfen Details in diesem Link http://docs.oracle.com/cd/E23824_01/html/821-1461/nc-1.html)

Beispiel von nc von der obigen Seite,

Connect to TCP port, send some data and terminate the connection with 
TCP RST segment 
(instead of classic TCP closing handshake) by setting the linger option and 
timeout to 0: 

$ echo "foo" | nc -L 0 host.example.com 22 
+0

Danke für Ihre Antwort, detailliert und klar. Leider kann ich die von Ihnen vorgeschlagene nc-Option nicht testen, da der Befehl auf meinem Linux-Rechner dies anscheinend nicht unterstützt.Übrigens sind die Dokumentation, auf die Sie mich hingewiesen haben, und die Erläuterungen, die Sie mir gegeben haben, klar und nützlich. Vielen Dank! – Igor

Verwandte Themen