Zum Inhalt springen

Linux Posix sockets


laladipsipo

Empfohlene Beiträge

Hallo,

Ich habe eine socket Schittstelle unter Linux unter Verwendung der normalen POSIX sockets implementiert. Auf der anderen Seite holt ein QT socket Client die Daten ab. Die Daten können mehrere Megabyte betragen und werden unter Verwendung eines TCP/IP sockets versendet.

Bei Tests ist aufegefallen, dass der Linux system call "write" nicht korrekt funktioniert, wenn der socket vorher in den "non blocking mode" versetzt wurde. Wird die "write" Funktion mit einem großen Datenbuffer (z.B. 132kByte) im blockierenden Modus aufgerufen, so segmentiert das OS die Daten korrekt und alle Daten werden vom Client empfangen.

Da ich aber in meinem Sender nicht warten kann, versetze ich den socket in den "non blocking mode". In diesem Fall werden bei Verwendung des gleichen write Befehls nur etwa 49152 Byte versendet. Danach werden vom Server keine weiteren Daten gesendet.

Ich denke, dass es sich bei den ersten 49152 Byte um den ersten Transmit Buffer des TCP/IP Stacks handelt. Mir ist jedoch nicht klar, warum nur der erste Buffer gesendet wird. Das Verhalten ändert sich auch dann nicht, wenn man nach Aufruf des "write" Befehls mehrere Sekunden wartet. Ich hätte erwartet, dass der TCP/IP Stack auch im nicht blockierenden Modus alle Daten versendet, wenn man den socket ansonsten in Ruhe lässt. Immerhin teste ich den socket vor dem nächsten Zugriff mit einem select Statement ab, ob er zum Senden neuer Daten bereit wäre.

Ist das ein absichtlich so implementiertes Verhalten oder vielleicht noch ein Bug im TCP/IP Stack?

System: openSUSE 10.2, Kernel 2.6.18, gcc 4.1.2

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich bin von Deiner Aussage "Der Sender kann nicht warten" ausgegangen, denn für mich hört sich das nach einem Streaming an. Bei so etwas würde ich definitiv UDP einsetzen.

Ich gehe davon aus, dass Deine Vermutung mit einem Bug falsch ist, denn es wäre sicherlich längst bekannt. Bitte wirklich einmal diesen Paragraphen lesen: Wie man Fragen richtig stellt: eine Anleitung wie man Fragen erfolgreich in Usenet, Mailing Listen und Webforen stellt.

Ich würde eher darauf tippen, dass Dein Konzept nicht gut genug ausgearbeitet ist, denn im Grunde steht in Deinem Post "geht nicht" und das ist nicht aussagekräftig. Überdenke Dein Konzept oder poste dieses mit allen relevanten Details, die notwendig sind, um Deine Problemstellung nachvollziehen zu können

Phil

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo,

Tut mir leid, wenn ich dich verärgert habe. Ich denke aber, dass meine Problembeschreibung ausreichend ist. Ich habe auch Tests mit UDP gemacht. Allerdings ist es für die Übertragung entscheidend, dass die Daten komplett und in der richtigen Reihenfolge übertragen werden. Diese Arbeit möchte ich mir vom TCP Protokoll abnehmen lassen. Bei UDP hätte ich das oben genannte Problem ja gar nicht, da ich selbst meine Daten segmentieren muss. Das ist mir klar. Als Resultat müsste ich dann aber einen komplizierten Protokolloverhead implementieren, der mir die sichere Datenübertragung garantiert.

Das eigentliche Problem ist, dass ich mit dem gleichen "write" System call im blockierendem und nicht blockierendem Modus unterschiedliches Verhalten habe:

Fall 1: (socket im blocking mode)

-write wird aufgerufen

-system call blockiert, bis alle Daten übertragen wurden.

-dabei werden mehere Transmits mit der maximalen Transmitbuffergröße von 49152 (auf meinem System) Byte gemacht.

-return value ist Anzahl der zu sendenden Bytes. errno ist 0

Fall 2: (socket im non blocking mode)

-write wird aufgerufen

-system call blockiert nicht. Die aufrufende Funktion pausiert aber nach dem write Kommando für 30 Selunden (also genug zeit, die Daten zu senden)

-dabei werden einmalig 49152 Byte gesendet, egal wie lange ich vor dem nächsten Aufruf warte

-return value ist jetzt nur 49152. errno ist aber trotzdem 0

Ich hoffe, dass macht es klarer.

Mein Problem ist, dass die Aufrufende Funtkion im Thread kontext läuft und das Gesamtprogramm nicht warten kann, bis alle Daten gesendet sind. Ich hätte erwartet, dass dieses vom Network Subsystem automatisch geleistet wird. Vielleicht liege ich da ja auch falsch. Ich habe oben in keinem fall geschrieben "geht nicht", sondern wollte viel mehr wissen, ob meine Erwartung falsch ist. Dann kann ich dass Problem umgehen, in dem ich einen zweiten Thread aufsetze, der den socket im blockierenden Modus betreibt. Bevor ich diesen Aufwand treibe, möchte ich aber sicher sein, dass die erste Variante nicht funktioniert.

Bearbeitet von laladipsipo
Link zu diesem Kommentar
Auf anderen Seiten teilen

Naja, scheint sich geklärt zu haben:

If the O_NONBLOCK flag is set using fcntl() (defined in <sys/fcntl.h> and explained in fcntl(2) and fcntl(5)), POSIX-style nonblocking I/O is enabled. In this case, the send() request completes in one of three ways:

  • If there is enough space available in the system to buffer all of the data, send() completes successfully, having written out all of the data, and returns the number of bytes written.

  • If there is not enough space in the buffer to write out the entire request, send() completes successfully, having written as much data as possible, and returns the number of bytes it was able to write.

  • If there is no space in the system to buffer any of the data, send() completes, having written no data, and returns -1, with errno set to

[EAGAIN].

Quelle: HP Developers pages.

Die Beschreibung gilt dort zwar nicht direkt für Linux, aber Posix ist ja ein übergreifender Standard.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Tut mir leid, wenn ich dich verärgert habe. Ich denke aber, dass meine Problembeschreibung ausreichend ist.

Das nicht, nur dass Du mit der Aussage "ich hab nen Bug gefunden" sehr vorsichtig sein solltest.

Mein Problem ist, dass die Aufrufende Funtkion im Thread kontext läuft und das Gesamtprogramm nicht warten kann, bis alle Daten gesendet sind. Ich hätte erwartet, dass dieses vom Network Subsystem automatisch geleistet wird. Vielleicht liege ich da ja auch falsch. Ich habe oben in keinem fall geschrieben "geht nicht", sondern wollte viel mehr wissen, ob meine Erwartung falsch ist. Dann kann ich dass Problem umgehen, in dem ich einen zweiten Thread aufsetze, der den socket im blockierenden Modus betreibt. Bevor ich diesen Aufwand treibe, möchte ich aber sicher sein, dass die erste Variante nicht funktioniert.

Also ich denke dass eben das Konzept falsch ist und es nicht an der Codierung hakt. Wenn Du Transportsicherheit brauchst, dann nimm TCP, wenn Du Streaming brauchst UDP. Im Moment versuchst Du meiner Ansicht nach UDP mit TCP zu mixen, nämlich die Fähigkeit von Streamining aus UDP mit der Transportsicherheit von TCP. Ich denke Du musst an die Problemstellung ran und da Du auf TCP setzen willst, musst Du Deine Struktur, die Dir die Daten passend zum Versand vorbereitet ändern, so dass sie mit TCP arbeitet.

Ich denke es ist weder eine Sache oder gar ein Fehler des Socket oder Deiner eigentlichen Übertragungsroutinen, sondern eben viel mehr der gewaltsame Versuch Fehler in der Vorverarbeitung durch das Protokoll / Schnittstelle zu beheben. Wenn Du aus mehreren Threads über das Netzwerk Daten sendest, warum synchronisierst Du sie nicht, sammelst dann die sychronisierten Daten und bereitest sie passend für den Versand auf und schickst sie dann rüber

Phil

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...