2009-06-25 6 views
9

Ich schreibe gerade ein Nachrichtenprotokoll über einen TCP-Stream. Der Empfänger muss wissen, wo die Nachrichtengrenzen sind.Schreiben eines Stream-Protokolls: Feld für Nachrichtengröße oder Nachrichtenbegrenzer?

Ich kann entweder senden 1) feste Länge Nachrichten, 2) Größe Felder, so dass der Empfänger weiß, wie groß die Nachricht ist, oder 3) eine eindeutige Nachricht Terminator (ich denke, das kann nirgendwo sonst in der Nachricht verwendet werden) .

Ich werde # 1 aus Effizienzgründen nicht verwenden.

Ich mag # 2, aber ist es möglich, dass der Stream nicht mehr synchron ist?

Ich mag Idee # 3 nicht, weil es bedeutet, Empfänger kann nicht die Größe der Nachricht im Voraus wissen und erfordert auch, dass der Terminator nicht an anderer Stelle in der Nachricht angezeigt wird.

Mit # 2, wenn es möglich ist, aus der Synchronisation zu kommen, kann ich einen Terminator hinzufügen oder bin ich garantiert nie aus der Synchronisation, solange das Sendeprogramm in dem, was es sendet, korrekt ist? Ist es notwendig, # 2 UND # 3 zu tun?

Bitte lassen Sie es mich wissen.

Danke, JBU

Antwort

5

Sie TCP verwenden, ist das Paket Lieferung zuverlässig. So wird die Verbindung entweder unterbrochen, Timeouts oder Sie werden die gesamte Nachricht lesen. Also Option # 2 ist in Ordnung.

3

Abhängig von der Ebene, auf der Sie arbeiten, hat # 2 möglicherweise keine Probleme mit der Synchronisierung (TCP hat Sequenznummerierung in den Paketen und setzt den Stream in der richtigen Reihenfolge für Sie neu, wenn es ankommt außer Betrieb).

Daher ist # 2 wahrscheinlich die beste Wahl. Wenn Sie die Nachrichtengröße zu einem frühen Zeitpunkt der Übertragung kennen, wird es außerdem einfacher, Speicher auf der Empfängerseite zuzuordnen.

+0

_Wenn Sie die Nachrichtengröße bereits zu Beginn der Übertragung wissen, wird es einfacher, Speicherplatz auf der Empfängerseite zuzuweisen._ Ein vorsichtiger Hinweis: Stellen Sie sicher, dass die Speicherzuweisung begrenzt wird. Andernfalls sind Sie anfällig für DDoS-Angriffe mit benutzerdefinierten Paketen, die ein Größenfeld von 2^32-1 haben (oder wie groß Ihre Ganzzahlen auch sind), wodurch Ihr Speicher schnell gefüllt wird. – Kenji

1

Wenn Sie sowohl den Sende- als auch den Empfangscode von Grund auf entwickeln, würde es nicht schaden, sowohl Längen- als auch Trennzeichen zu verwenden. Dies würde Robustheit und Fehlererkennung bereitstellen. Betrachten Sie den Fall, in dem Sie nur # 2 verwenden. Wenn Sie ein Längenfeld von N in den TCP-Stream schreiben, aber am Ende eine Nachricht senden, die eine andere Größe als N hat, würde das empfangende Ende nichts besseres wissen und am Ende verwirrt sein.

Wenn Sie sowohl # 2 als auch # 3 verwenden, obwohl nicht idiotensicher, kann der Empfänger ein größeres Maß an Vertrauen haben, dass er die Nachricht korrekt empfangen hat, wenn er das Trennzeichen nach dem Verbrauch von N Bytes aus dem TCP-Stream findet. Sie können auch das Trennzeichen in Ihrer Nachricht verwenden.

Werfen Sie einen Blick auf HTTP Chunked Transfer Coding für ein echtes Beispiel der Verwendung von # 2 und # 3.

2

Ich stimme mit sigjuice überein. Wenn Sie ein Größenfeld haben, ist es nicht erforderlich hinzuzufügen und Ende der Nachricht Delimiter - jedoch ist es eine gute Idee. Mit beiden macht die Dinge viel robuster und einfacher zu debuggen.

Verwenden Sie den Standard netstring format, der sowohl ein Größenfeld als auch ein Zeichenende enthält. Da es ein Größenfeld hat, ist es OK, dass das Zeichenendezeichen innerhalb der Nachricht verwendet wird.

0

Es gibt eine vierte Alternative: ein selbstbeschreibendes Protokoll wie XML.

+0

Dies ist für reine Binärnachrichten ungeeignet. Es ist im Grunde Option # 3, aber viel schlechter als ein einzelnes Trennzeichen. – Lucretiel

2

Interessant gibt es keine klare Antwort hier. # 2 ist über TCP sicher, egal was passiert, und wird "oft in der realen Welt" ausgeführt. Dies liegt daran, dass TCP garantiert, dass alle Daten sowohl in unveränderter Reihenfolge als auch in der Reihenfolge, in der sie gesendet wurden, ankommen. Daher besteht keine Möglichkeit, dass eine korrekte Implementierung nicht synchron läuft.

Verwandte Themen