2010-08-26 13 views
6

Ich verwende blockierende C-Sockets unter Windows. Ich verwende sie, um Aktualisierungen von Daten vom Server zum Client zu senden und umgekehrt. Ich sende Updates mit einer hohen Frequenz (alle 100ms). Funktioniert die send() Funktion auf den Empfänger recv(), um die Daten vor dem Beenden zu empfangen?C-Socket: sendet send warten auf recv zu beenden?

Ich gehe davon aus, wenn ich nicht gut in die Manpage verstehen: „Die erfolgreiche Abschluss von send() bietet keine Garantie für die Lieferung der Nachricht“

Also, was passiert, wenn man 10 send() Vorkommnissen läuft, während die andere nur komplett 1 recv() hat?

Muss ich so eine Art Quittungs-System verwenden?

+0

Was ist der Protokolltyp des Sockets? TCP, UDP, etwas anderes? – torak

+0

Ich benutze TCP-Protokoll – Giann

Antwort

10

Nehmen wir an, Sie verwenden TCP. Wenn Sie send senden, werden die Daten, die Sie senden, sofort in die ausgehende Warteschlange gestellt, und send wird dann erfolgreich abgeschlossen. Wenn send jedoch nicht in der Lage ist, die Daten in die ausgehende Warteschlange zu stellen, wird send mit einem Fehler zurückgegeben.

Da es sich bei Tcp um ein garantiertes Übertragungsprotokoll handelt, können die Daten in der ausgehenden Warteschlange nur entfernt werden, wenn das entfernte Ende eine Bestätigung erhalten hat. Dies liegt daran, dass die Daten möglicherweise erneut gesendet werden müssen, wenn keine Bestätigung rechtzeitig empfangen wurde.

Wenn das Remote-Ende träge ist, wird die ausgehende Warteschlange mit Daten gefüllt und das Senden wird dann blockiert, bis Platz vorhanden ist, um die neuen Daten in der ausgehenden Warteschlange zu platzieren.

Die Verbindung kann jedoch so ausfallen, dass keine weiteren Daten mehr gesendet werden können. Obwohl nach dem Schließen einer TCP-Verbindung weitere Übertragungen zu einem Fehler führen, kann der Benutzer nicht wissen, wie viele Daten tatsächlich zur anderen Seite geführt haben. (Ich kenne keine Möglichkeit, die TCP-Buchhaltung von einem Socket in die Benutzeranwendung zurückzuholen). Wenn daher eine Bestätigung des Datenempfangs erforderlich ist, sollten Sie dies wahrscheinlich auf Anwendungsebene implementieren.

Für UDP, ich denke, es versteht sich von selbst, dass eine Art und Weise der Berichterstattung, was oder nicht erhalten wurde, ein Muss ist.

7

send() blockiert, bis das Betriebssystem (Kernel) die Daten genommen und in einen Puffer ausgehenden Daten abgelegt hat. Es wartet nicht, bis das andere Ende die Daten erhalten hat.

0

Wenn Sie TCP verwenden, erhalten Sie die Bestätigungen kostenlos, da dies Teil dessen ist, was das Protokoll unter der Haube tut. Aber klingt wie für diese Art von Anwendung, die Sie wahrscheinlich UDP verwenden möchten. In beiden Fällen wird send() jedoch erst blockiert, wenn der Client erfolgreich recv() hat.

Wenn es wichtig ist, dass der Client jede Nachricht erhält, dann verwenden Sie TCP. Wenn es für den Client in Ordnung ist, eine oder mehrere Nachrichten zu verpassen, verwenden Sie UDP.

+1

Sie erhalten Acks auf der TCP-Schicht, aber das hilft Ihnen nicht, wenn Sie Acks auf der Anwendungsebene benötigen, dh wenn Sie wissen müssen, dass eine Nachricht empfangen wurde, müssen Sie Acks in welcher Anwendung implementieren Protokoll, das Sie verwenden. – nos

2

Wenn Sie per TCP senden, erhalten Sie garantiert Lieferung und das andere Ende wird die Daten in der Reihenfolge gesendet erhalten. Dies könnte jedoch zusammengewachsen werden, so dass das, was Sie als 10 separate Aktualisierungen gesendet haben, als einzelnes großes Paket empfangen werden könnte (oder umgekehrt - ein einzelnes Update könnte über eine willkürliche Anzahl von Paketen aufgeteilt werden). Dies bedeutet unter anderem, dass jede ACK beliebiger Daten implizit den Empfang aller vorherigen Daten bestätigt.

Wenn Sie UDP verwenden, ist das alles nicht wahr - Daten können außerhalb der Reihenfolge ankommen oder gelöscht werden und überhaupt nicht geliefert werden. Wenn Sie sich um alle empfangenen Daten kümmern, müssen Sie nur eine Art eigenes Bestätigungssystem zusätzlich zu UDP selbst erstellen.

Natürlich gibt es ein Limit für die Garantie - wenn ein Netzwerkkabel abgeschnitten wird (oder was auch immer), werden Pakete nicht zugestellt, aber Sie erhalten zumindest eine Fehlermeldung, die Ihnen die Verbindung sagt war verloren.

0

TCP garantiert die Zustellung auf einem niedrigeren TCP-Stack-Level. Es wiederholt die Zustellung, bis der empfangende Teil bestätigt, dass die Daten empfangen wurden, aber Ihre Anwendung wird dies möglicherweise nie erfahren.

Nehmen wir an, Sie senden Teile von Daten und Sie müssen diese Datenblöcke irgendwo nach einer Logik platzieren. Wenn Ihre Anwendung nicht bereit ist zu wissen, wo jeder einzelne Block platziert werden muss, kann der Empfang auf TCP-Ebene nutzlos sein. Im ursprünglichen Post ging es um die Logik auf Anwendungsebene.

Verwandte Themen