Hallo zusammen, ich habe eine Frage bezüglich einer TCP/IP Kommunikation. Dies ist ja einfach ein Datenstream und wenn ich mir nun ein Protokoll, wie die Daten da übertragen werden, ausdenke, dann muss ich auch selber erkennen wo mein Frame anfängt und wo er aufhört, oder? Wie geht das denn bei anderen Protokollen wie z.B. Modbus TCP/IP? Wenn ich die recv. Funktion eines Sockets aufrufe und dort kein gültiger Frame anfang liegt habe ich doch ein Problem, korrekt? Gibt es eine Sinnvolle Lösung für dieses Problem? Besten Gruß Jens Edit: Bei mir geht es eben auch dadrum, dass ich in meinem eigenem "Frame" mehr Daten als die 1500 Bytes übertragen möchte und ggf. mehrere TCP/IP Frames dafür benötigt werden.
Jens S. schrieb: das Wird auf der untersten ebende gemacht, also nicht im IP sondern auf der MAC ebende. Ich konnte jetzt auf die schnell nicht finden wie dort ein anfang definierst ist, als beispiel kannst du dir aber HDLC anschauen dort gibt es eine feste Bitfolge. http://de.wikipedia.org/wiki/High-Level_Data_Link_Control
Hallo, da ich mich gerade vor 2 Monaten mit dem gleichen Thema beschäftigt hatte wage ich hier mal zu widersprechen. TCP liefert eigentlich nur einen Stream, d.h. es gibt keine Erkennung logischer Frames auf der Applikationsebene. Was man erkennt ist allerdings das allererste Byte, und die Übertragung ist gesichert, d.h. es kann keines unerkannt verloren gehen. Viele einfache Protokolle sind textorientiert (HTTP, FTP, SMTP, usw.), so daß man über das Zeilenende einen Parser steuern kann. Wir haben für unser binäres Protokoll Frames definiert, die z.B. mit der Längeninformation beginnen, d.h. - 2 Bytes lesen, Länge n auswerten - weitere n bytes lesen, das sind die Daten - nochmal 4 bytes Prüfsumme lesen Was tun, wenn die Prüfsumme nicht stimmt ? Bei uns kommt dann irgendwann ein Read-Timeout, nach dem wir von vorn beginnen. Es geht sicher auch einfacher, aber wie ? Gruß, Michael
Hallo Michael, genau das Vorgehen hatte ich mir nun auch überlegt. Die Frage bleibt dann einfach ob es noch eine bessere Methode gibt. Grundsätzlich dürften ja im RecvBuffer des TCP/IP Stacks keine verwahrlosten Daten sein wie z.b. Störbytes bei einer Seriellenkommunikation.
Hallo Jens, genau das war so, mit TCP/IP war die Kommunikation absolut sauber. In unserem Fall lag optional ein UMTS-Modem per serieller Schnittstelle in der Übertragung (kein TCP/IP), und das hat gelegentlich Bytes verloren. Das hat dann unserr Lesen mit Timeout abgefangen. Störbytes gab es aber keine. Gruß, Michael
wenn es nicht schnell sein muss kannst du den socket auch öffnen schließen. socket auf, daten rein, socket zu. ist langsam, verhindert aber dass sockets offen bleiben, du musst dich nicht um start oder end oder prüfsumme kümmern. ein anderes Problem beim lesen aus einem offenen socket ist dass zwar alle pakete übertragen werden, diese aber in unterschiedlicher reihenfolge bei dir auschlagen dürfen. es gibt also die möglichkeit dass dir im stream ein stück fehlt, das zwar danach gelifert ( oder noch einmal vom socket angefordert wird), du aber bereits ein streamstück mit "Loch" gelesen hast. siehe http://commons.wikimedia.org/wiki/File:Tcp_transfer.png wenn es dir aslo nicht auf das letzte ms ankommt dann mach das ding auf und wieder zu nach jeder übertragung.
Clemens S. schrieb: > ein anderes Problem beim lesen aus einem offenen socket ist dass zwar > alle pakete übertragen werden, diese aber in unterschiedlicher > reihenfolge bei dir auschlagen dürfen. es gibt also die möglichkeit dass > dir im stream ein stück fehlt, das zwar danach gelifert ( oder noch > einmal vom socket angefordert wird), du aber bereits ein streamstück mit > "Loch" gelesen hast. nein das kann nicht passieren, sonst könnte man mit TCP gar nicht arbeiten. Das kann nur bei UDP passieren. Der Stack gibt dir die packete immer in der richtige Reihenfolge egal wie sie am PC eintreffen.
Clemens S. schrieb: > ein anderes Problem beim lesen aus einem offenen socket ist dass zwar > alle pakete übertragen werden, diese aber in unterschiedlicher > reihenfolge bei dir auschlagen dürfen. es gibt also die möglichkeit dass > dir im stream ein stück fehlt, das zwar danach gelifert ( oder noch > einmal vom socket angefordert wird), du aber bereits ein streamstück mit > "Loch" gelesen hast. Das sind ja ganz neue Erkenntnisse! Ich glaube alle außer dir benutzen ein anderes TCP/IP Protokoll... Clemens S. schrieb: > wenn es nicht schnell sein muss kannst du den socket auch öffnen > schließen. socket auf, daten rein, socket zu Dann kann er auch gleich UDP mit einem ACK Verfahren nutzen...
ja, die reihenfolge stimmt und es werden auch alle daten übertragen. bis zum ack der verbindung ist es aber nicht sicher dass du das paket auch bereits zum abruf hast
Clemens S. schrieb: > ja, die reihenfolge stimmt und es werden auch alle daten > übertragen. bis zum ack der verbindung ist es aber nicht sicher dass du > das paket auch bereits zum abruf hast Dunkel ist der Sinn deiner Worte...
Also wenn ich meine recv bsd socket Funktion aufrufe, dann sind die Daten dort gültig. Die verlorenen bzw. falsche Telegramreihenfolge ist ja alles ein paar Ebenen tiefer. Darum möchte ich mich garnicht kümmern und macht ja auch der TCP/IP Stack von Windows CE. Somit werde ich zur Sicherheit noch einen Timeout einbauen und eine CRC Checksumme. Immer den Socket neu aufmachen bedeutet ja auch eine neue Task zu öffnen und, bei meiner aktuellen Konsturktion, auch etwas mehr aufwand weil beim Anlegen des Clients ein paar Sachen passieren. Alternativ müsste man drüber nachdenken 2 Socket Verbindungen aufzubauen. Eine mit der Configuration/Alive und eine für den Datenaustausch der immer geöffnet, geschlossen wird.
Timeout ist wichtig, auf CRC kannst du verzichten. Die Kommunikation fängt ja so an das der Client einen Verbindungsversuch zum Server macht. Wenn der aktzeptiert sind die Buffer leer und die Verbindung ist synchron. Jetzt sollte dein Protokoll so aussehen das du z.B. zuerst eine Messagelänge und dann eine ID sendest. Der Empfänger kann dann den Rest der Message lesen und die nächste muss halt wieder genauso anfangen. Solange Bytes beim Empfänger ankommen sind bei TCP auch in der richtigen Reihenfolge. Durch die Angabe der Länge kann der Empfänger auch unbekannte Nachrichten empfangen ohne ausser Tritt zu kommen. Was aber passieren kann ist ein Verbindungsabbruch, z.B. durch Stecker ziehen. Das kriegt der Empfänger evtl nicht mit und deshalb ist ein Watchdog + Timeout nötig. Wenn der Gegner das Timeout erkennt muss die Verbindung geschlossen und wieder neu aufgebaut werden damit es wieder synchron losgehen kann.
Die recv bzw. send Funktion geht doch mit einem Wert <0 raus und erkennt den Connection_Lost und ich weiß, dass die Verbindung weg ist. Dann wird der Socket mit dem Client geschlossen und auf eine neue Verbindung gewartet und alles fängt von vorne an :) Also ich hatte bei mir nicht geplant auch Frames, die mit eineem Verbindungsproblem zerstückelt wurden, wieder weiter zu verarbeiten.
Jenss schrieb: > ie recv bzw. send Funktion geht doch mit einem Wert <0 raus Das kommt auf die Verbindungsstrecke an, es ist nicht gut sich darauf zu verlassen. Wenn man das Netzwerkabel direkt vom Rechner abzieht wird das mittlerweile durch den IP Stack geleitet und der Applikation gemeldet. Sind aber Router, Switches, Glasfaser oder Funk dazwischen bekommt man das nicht sicher mit wenn man in einer recv() Schleife hängt. Deshalb ist die Timeout Erkennung auf Applikationsebene wichtig, das macht den Unterschied zwischen einem funktionierenden und einem robusten Programm aus.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.