2009-08-03 4 views
10

Ich habe die Booster-Asio-Referenz gelesen, bin durch das Tutorial gegangen und habe einige Beispiele betrachtet. Dennoch kann ich nicht sehen, wie ein Sockel abgerissen werden sollte:Wie sollte man einen boost :: asio :: ip :: udp :: socket abreißen?

  1. Sollte ich close() aufrufen oder wird dies durch den Destruktor des Sockets getan?
  2. Wann sollte ich shutdown() anrufen
  3. Was sind die Auswirkungen von shutdown()? Ich bin mir bewusst, dass es "deaktiviert sendet oder empfängt", aber wie ist das gemacht? Was kann ich erwarten, wenn ich den Socket nach der Deaktivierung sende oder empfange?
  4. Welche Fehler kann ich aus der Nähe erwarten()

Antwort

10

Da es sich um eine Multi-Frage, ich werde mein Bestes tun, um jeden Teil zu Ihrer Zufriedenheit zu beantworten:

1) Es war meine Erfahrung mit ASIO-Sockets, die der Destruktor beim Schließen des Sockets handhabt. Ich habe mich jedoch nur mit TCP-Sockets beschäftigt. Der beste Weg, dies zu überprüfen, besteht darin, einfach den Code für den Destruktor zu betrachten, um zu sehen, ob er etwas ähnlich wie ein Schließen tut. Ich weiß, dass Boost-Code ein wenig trickreich sein kann, so dass es am einfachsten ist, einfach ein kleines Beispielprogramm zu erstellen, das einen UDP-Socket öffnet und es dann zerstört. Auf diese Weise können Sie den Code in einem Debugger durchlaufen, um der Logik zu folgen.

Da die Designer von Boost dies bei TCP-Sockets berücksichtigten, fällt es mir schwer, mir vorzustellen, dass sie das nicht auch für UDP-Sockets tun würden.

2) Rufen Sie shutdown() nur an, wenn Sie glauben, dass es notwendig ist, zu verhindern, dass ein Code eine zukünftige recv und/oder send auf dem Sockel ausführt. Es ist normalerweise nicht erforderlich, obwohl ich gesehen habe, dass es in TCP-Sockets verwendet wird, um den Socket zu zwingen, eine RST zu senden, wenn es geschlossen ist (im Gegensatz zu dem standardmäßigen "anmutigen" Herunterfahren, bei dem ausstehende Sends verarbeitet werden).

3) Sie können sich Sockets als zweikanalige Kommunikationsform vorstellen: eine zum Lesen, die andere zum Senden. Sie können beide unabhängig voneinander herunterfahren, und Sie können weiterhin einen Kanal verwenden, wenn der andere heruntergefahren ist (d. H. Sie können immer noch nach dem Herunterfahren zum Senden empfangen und umgekehrt). Das Schließen eines Sockets ist identisch mit dem Aufruf von shutdown sowohl bei recv als auch bei send.

Das Herunterfahren für recv verhindert einfach, dass Ihr Code keine weiteren Daten mehr lesen kann. Wenn Sie dies versuchen, erhalten Sie einen Socket-Fehler. Wenn die andere Seite der Verbindung versucht, Daten an Sie zu senden, wird ebenfalls ein Fehler angezeigt (es tut uns leid, wieder in die TCP-Welt zu wechseln, aber ich glaube, dass eine RST zurück an den Absender gesendet wird).

Das Herunterfahren zum Senden verhindert ebenfalls, dass Ihr Code weitere Daten sendet. Wenn Speicher mir richtig dient, sieht das identisch aus, was passiert, wenn Sie einen Socket schließen (ein Null-Länge-Paket wird gesendet, um der anderen Seite zu signalisieren, dass der bestimmte Kanal heruntergefahren wurde). Alle zukünftigen Sendeversuche geben einen Fehler zurück.

4) Sie müssen Ihre Dokumente überprüfen, um sicher zu sein. MSDN wird Ihnen einen ziemlich guten Hinweis geben, obwohl ich nicht weiß, dass ich es für autoritativ halten würde.

+0

Danke, ich habe einige dieser herausgefunden, aber ich bin immer noch nicht sicher, ob close() wirklich in der Destruktor der Buchse genannt wird. Was ich wirklich nicht gemunkelt hatte, war die enge Verbindung zwischen Boost Asio und traditioneller Netzwerkprogrammierung. Sowohl Ihre Erklärung von shutdown() als auch der Vorschlag, in msdn-Socket-Fehlercodes zu suchen, legen dies nahe. +1 – Torleif

+0

Froh ich könnte helfen :) – Brian

+0

FWIW, Aufruf .shutdown (BEIDE) auf einem UDP-Socket funktioniert für mich auf Windows, aber explodiert unter Linux, weil der Socket nicht verbunden ist. –

1

Aus den Beispielen auf der Boost-Website scheint es, als ob Sie einfach close() verwenden sollten.Zum Beispiel, schauen Sie sich dieses:

 
void connection::stop() 
{ 
    socket_.close(); 
} 

von dieser Adresse Genommen: HTTP Server