nicht-blockierende Udp-Socket-Programmierung in C: Was bekomme ich?

8

Ich habe ein Problem zu verstehen, was recv () / recvfrom () von einem nicht-blockigen UDP-Socket zurückgibt.

Ein bisschen spezifischer und im Vergleich zu TCP (bitte korrigieren Sie mich, wenn ich falsch liege):

  • Ein blockierender Socket (entweder TCP oder UDP) wird nicht von einem recv () zurückgegeben, bis einige Daten im Puffer vorhanden sind. Dies kann eine bestimmte Anzahl von Bytes (TCP) oder ein vollständiges Datagramm (UDP) sein.

  • Ein nicht blockierender TCP-Socket gibt entweder EWOULDBLOCK (linux) / WSAEWOULDBLOCK (windows) oder die Bytes zurück, die sich gerade im Puffer befinden. Da TCP-Daten ein Stream sind, ist es egal, wie viele Bytes zurückgegeben werden.

Jetzt die Frage:

  • Ein nicht blockierender UDP-Socket gibt auch WOULDBLOCK (linux) / WSAEWOULDBLOCK (windows) zurück, wenn keine Daten verfügbar sind. Aber wenn Daten verfügbar sind, gibt ein nicht blockierender UDP-Socket nur einige Bytes zurück, was bedeuten könnte, dass Sie nur die Hälfte eines Datagramms erhalten ODER liefert ein UDP-Socket immer vollständige Datagramme?

Bearbeiten:

Was ich mit "einem halben Datagramm" meine, ist: Was passiert, wenn ich recv () gerade in dem Moment anrufe, in dem der Socket gerade ein Datagramm empfängt? In diesem Moment befinden sich einige Bytes im Puffer, aber das Datagramm ist noch nicht vollständig.

Ihre Erklärungen und Kommentare sind willkommen. Danke!

    
Uwe 10.02.2010, 20:09
quelle

3 Antworten

8

Endlich eine Entschuldigung, um meine Stevens-Bücher aus meinen alten Bürokästen auszugraben.

Wenn der Puffer groß genug ist, geben die standardmäßigen Berkeley-Sockets recv() und recvfrom() -Funktionen niemals ein Teil-Datagramm zurück. Das Datagramm ist für die Anwendung erst verfügbar, wenn der Kernel das Datagramm vollständig empfangen und wieder zusammengesetzt hat.

Interessanterweise, und das ist nicht viel (irgendein?) eines Problems heute, andere Netzwerkprogrammierschnittstellen stimmen nicht auf das Verhalten überein, wenn der zur Verfügung gestellte Puffer zu klein ist:

  

Die traditionelle Berkeley-Version der Sockets-API schneidet das Datagramm ab und löscht alle überflüssigen Daten. Ob die Anwendung benachrichtigt wird, hängt von der Version ab. (4.3BSD Reno und später können der Anwendung mitteilen, dass das Datagramm abgeschnitten wurde.)

     

Die Socket-API unter SVR4 (einschließlich Solaris 2.x) schneidet das Datagramm nicht ab. Überzählige Daten werden bei nachfolgenden Lesevorgängen zurückgegeben. Die Anwendung wird nicht benachrichtigt, dass mehrere Lesevorgänge von einem einzelnen UDP-Datagramm erfüllt werden.

     

Die TLI-API verwirft die Daten nicht. Stattdessen wird ein Flag zurückgegeben, das anzeigt, dass mehr Daten verfügbar sind, und nachfolgende Lesevorgänge durch die Anwendung geben den Rest des Datagramms zurück.

(Stevens, TCP / IP Illustriert, Band 1, S. 160)

    
Steve Madsen 10.02.2010, 22:16
quelle
1

Ja, UDP gibt nur zurück, welche Daten in diesem einen Datagramm übertragen wurden. UDP ist nicht stream-orientiert wie TCP. Datagramme sind diskrete Übertragungen und sind in keiner Weise wirklich an andere Datagramme gebunden. Aus diesem Grund ist die Socket-Option für TCP SOCK_STREAM.

Die helle Seite davon ist, dass Sie ein Gefühl für getrennte Übertragungen bekommen können, was mit TCP nicht wirklich einfach ist.

    
T.E.D. 10.02.2010 20:23
quelle
0

Ich glaube, Sie erhalten genau ein oder null Datagramme. Aber das kann ich in diesem Moment nicht bestätigen. Vielleicht könnte jemand anderes eine gute Referenz geben?

Bearbeiten: Ich bin mir ziemlich sicher, dass du kein halbes Datagramm empfangen kannst. Entweder ist das Datagramm im Puffer angekommen oder nicht.

    
Hans W 10.02.2010 20:22
quelle