2010-12-28 10 views
0

Ich schreibe ein Programm mit Java non-blocking Socket und TCP. Ich verstehe, dass TCP ein Stream-Protokoll ist, aber das Underlayer-IP-Protokoll verwendet Pakete. Wenn ich SocketChannel.read (ByteBuffer dst) anrufe, bekomme ich dann immer den ganzen Inhalt von IP-Paketen? oder es kann an jeder Position in der Mitte eines Pakets enden?Nicht blockierende Socket mit TCP

Das ist wichtig, weil ich versuche, einzelne Nachrichten über den Kanal zu senden. Jede Nachricht ist klein genug, um in einem einzigen IP-Paket gesendet zu werden, ohne fragmentiert zu werden. Es wäre cool, wenn ich immer eine ganze Nachricht bekommen könnte, indem ich read() auf der Empfängerseite aufruft, ansonsten muss ich eine Methode implementieren, um die Nachrichten wieder zusammenzusetzen.

Bearbeiten: angenommen, dass auf der Senderseite Nachrichten mit einem langen Intervall (wie 1 Sekunde) gesendet werden, so dass sie nicht in einem IP-Paket gruppieren. Auf der Empfängerseite ist der zum Lesen verwendete Puffer (ByteBuffer dst) groß genug, um irgendeine Nachricht zu halten.

Antwort

2

TCP ist ein Stream von Bytes. Jeder Lesevorgang erhält zwischen 1 und dem Maximum der von Ihnen angegebenen Puffergröße und der Anzahl der Bytes, die zu diesem Zeitpunkt gelesen werden können.

TCP weiß nichts von Ihrem Konzept der Nachrichten. Jedes Senden durch den Client kann dazu führen, dass am anderen Ende 0 oder mehr Lesevorgänge erforderlich sind. Null oder mehr, weil Sie möglicherweise einen einzelnen Lesevorgang erhalten, der mehr als eine Ihrer "Nachrichten" zurückgibt.

Sie sollten Ihren gelesenen Code IMMER so schreiben, dass er mit Ihrem Nachrichtenrahmen umgehen und entweder Teilnachrichten wieder zusammensetzen oder mehrere teilen kann.

Sie können feststellen, dass, wenn Sie sich nicht mit dieser Komplexität beschäftigen, Ihr Code die meiste Zeit zu funktionieren scheint, verlassen Sie sich nicht darauf. Sobald Sie in einem belebten Netzwerk oder über das Internet arbeiten oder sobald Sie die Größe Ihrer Nachrichten erhöhen, werden Sie von Ihrem kaputten Code gebissen.

ich über TCP Nachricht sprechen etwas mehr hier Framing: http://www.serverframework.com/asynchronousevents/2010/10/message-framing-a-length-prefixed-packet-echo-server.html und hier: http://www.serverframework.com/asynchronousevents/2010/10/more-complex-message-framing.html obwohl es im Hinblick auf eine C++ Implementierung ist so kann es oder nicht für Sie von Interesse sein kann.

0

Von der SocketChannel Dokumentation:

A socket channel in non-blocking mode, for example, cannot read 
any more bytes than are immediately available from the socket's input buffer; 

Also, wenn Ihr Zielpuffer groß genug ist, Sie sollen Eingangspuffer die gesamten Daten konsumieren können, in der Fassung der.

1

Die Socket-API gibt keine Garantie dafür, dass send() - und recv() - Aufrufe mit Datagrammen für TCP-Sockets korrelieren. Auf der sendenden Seite können Dinge bereits neu gruppiert werden, z. das System kann das Senden eines Datagramms verzögern, um zu sehen, ob die Anwendung mehr Daten hat; Auf der Empfangsseite kann ein Leseaufruf Daten von mehreren Datagrammen abrufen oder ein Teildatagramm, wenn die vom Anrufer angegebene Größe ein Breaking-Paket erfordert.

IOW, die TCP-Socket-API setzt voraus, dass Sie einen Byte-Stream haben, nicht eine Sequenz von Paketen. Sie müssen sicherstellen, dass Sie weiterhin read() aufrufen, bis Sie genügend Bytes für eine Anfrage haben.