2016-06-15 6 views
3

Ich bin derzeit Daten über TCP/IP in myserver Senden so etwas wie dieses python Senden TCP/IP-Daten sofort

for str in lst: 
    data = str + "\n" 
    self._conn.sendall(data) 
mit jetzt in meiner Liste hat folgende zwei String nehme an, es

1-This is statement 1 in list 
2-This is statement 2 in list 

Mein Kunde erhält die Hälfte von Zeile 2 so.

This is statement 1 in list 
    This is 

Ich möchte Zeile1 und dann Zeile 2 in der Liste einzeln senden. Ich verstehe, dass TCP/IP so funktioniert, dass es die gesamten Daten sendet, die zum Senden verfügbar sind. Ich denke, ich könnte eine Verzögerung nach dem Aufruf self._conn.sendall(data) setzen, aber ich wollte wissen, welche anderen Optionen ich habe. Ich kann keine Änderungen am Empfänger der Daten vornehmen und kann nur Änderungen am Absender vornehmen. Bis jetzt ist meine einzige Option, eine Verzögerung nach jedem Senden hinzuzufügen.

+1

Der Client muss weiterhin Recv-Anrufe machen, bis alles vorhanden ist. Ich kenne Python nicht, daher kann ich keine spezifische Antwort geben. – kicken

+0

Wenn Sie die volle Kontrolle darüber haben möchten, was in jedem Paket gesendet wird, können Sie auch UDP verwenden. – Aya

Antwort

5

TCP arbeitet mit Datenströmen, nicht einzelnen Paketen. Es ist wie das Lesen von Daten aus einer Datei. Der Absender legt Daten in seinen Sendepuffer, und TCP kann selbst entscheiden, wann es gesendet werden soll. Der Zeitpunkt der Ankunft bei der empfangenden Anwendung hängt davon ab, wann die Daten gesendet wurden und auf (oft unvorhersehbaren) Netzwerkbedingungen.

TCP Lieferungen können mehr vorhersagbar gemacht werden, wenn Sie die TCP_NODELAY Flagge in Ihrer Steckdose (so etwas wie socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) verwenden. Dies würde TCP verursachen Daten zu senden, sobald es in seinem Puffer ankommt. Aber dennoch würde es keine Garantien sein Was die Ankunftszeiten angeht, würde jede zeitbasierte Lösung zumindest in einigen Fällen brechen

Die Lösung besteht darin, den Datenstrom in Stücke zu teilen. Es gibt mehrere Möglichkeiten, das zu tun. Hier sind ein paar:

  1. Nachrichten mit fester Länge verwenden - Wenn alle Nachrichten eine feste Länge haben, wird r eceiver muss nur recv() die richtige Anzahl von Bytes, verarbeiten Sie die Nachricht, dann warten Sie auf die gleiche Anzahl von Bytes.

  2. Senden Sie die Länge der Nachricht vor jeder Nachricht. Wenn Sie den String "blah" senden möchten, kodieren Sie ihn als "0004blah" oder etwas Ähnliches. Der Empfänger liest (immer) die ersten vier Bytes (die 0004 sind), um die Anzahl der verbleibenden zu lesenden Bytes herauszufinden. Es liest dann die erforderliche Anzahl von Bytes, verarbeitet die Nachricht und wartet dann auf die nächste. Es ist eine robuste Lösung, die auch einfach zu implementieren ist.

  3. Verwenden Sie ein Trennzeichen. Zeilen in Textdateien werden durch Zeilenumbruchzeichen (\n) geteilt. In ähnlicher Weise können Sie ein spezielles Begrenzungsbyte (oder Bytes) zwischen Nachrichten hinzufügen. Sie können beispielsweise festlegen, dass Nachrichten immer mit einem Dollarzeichen ($) enden. Dann muss der Empfänger nur noch von der Buchse Byte für Byte lesen, bis er ein Dollarzeichen erhält. Wenn Sie diesen Ansatz verwenden, müssen Sie natürlich sicherstellen, dass der Text der Nachrichten nicht das Trennzeichen enthält.

+1

Vielen Dank für das Aufräumen –

0

TCP basiert auf einem Stream, nicht einzelnen Nachrichten. Sie müssen also den Endpunkt jeder Nachricht selbst analysieren. Eine Idee in Ihrem Fall wäre zu lesen, bis Sie eine neue Zeile erhalten, dann die Zeile verarbeiten. Beachten Sie, dass Sie diese Zeilen lesen könnte:

This is statement 1 in list 
This is 

Dann müssen Sie überprüfen, um zu sehen, ob Sie eine neue Zeile bekam, verarbeiten Sie die Linie, dann Puffer verlassen bereit, den Rest zu erhalten, wie folgt aus:

This is 
+0

Können Sie mir ein Beispiel geben, wie ich das machen würde? –

+0

@JamesFranco: Klar: Lies einfach bis zu 1000 Zeichen in einen Puffer. Teile den Puffer auf Newline (''\ n''). Parsen Sie die ersten N-1-Chunks (das sind komplette Zeilen) und behalten Sie den letzten Chunk. Lesen Sie dann weiter, fügen Sie den Puffer hinzu und wiederholen Sie die obigen Schritte. –

0

TCP hat einen lokalen Puffer, der erst gesendet wird, wenn er voll ist. Sie können das Löschen des lokalen Puffers erzwingen, sodass er nach jeder Nachricht gesendet wird. Wenn die Gegenstelle diese Pakete empfängt, werden sie in einem anderen lokalen Puffer gespeichert und Ihre Trennung verschwindet möglicherweise. TCP ist ein Stream, benutze ihn als Stream. Sie müssen Trennzeichen verwenden und wenn die Pakete empfangen werden, müssen Sie die Nachrichten manuell trennen. Wenn Sie mehr Kontrolle wünschen, verwenden Sie UDP-Pakete.