2009-10-31 51 views
9

我已經寫了一個服務器在Python中,旨在以「頭:消息」的形式發送數據到客戶端如何刷新Python套接字?

我希望能夠單獨發送每條消息,以便客戶端需要執行最小的工作,以讀取「標題」和「消息」

不幸的是,我無法弄清楚如何正確地刷新一個python套接字,所以當我有多個發送快速連續執行消息會混在一起在套接字緩衝區中並作爲一個大塊發送。

例子:

服務器發送...

socket.send ("header1:message1") 
socket.send ("header2:message2") 
socket.send ("header3:message3") 

客戶端收到...... 「頭1:message1header2:message2header3:MESSAGE3」

我願意接受三個個人信息

header1:message1 
header2:message2 
header3:message3 

我需要一種方法來刷新eac後h send

+0

完全重複:http://stackoverflow.com/questions/1097974/how-to-flush-a-socket-in-python – ChristopheD 2009-10-31 20:46:49

+4

*不是重複:*標題是*字面*重複,但問題實際上*功能*不同。 OP需要一個答案,就像下面的@ebo一樣。 – 2009-10-31 20:50:51

+1

糟糕,這似乎是正確的。下次嘗試會慢一點;-) – ChristopheD 2009-10-31 20:58:59

回答

19

我猜你正在通過TCP連接進行通話。

您的方法有缺陷。 TCP流被定義爲一個字節流。您總是必須使用某種分隔符,並且可能不依賴網絡堆棧來分隔消息。

如果你真的需要基於數據報的服務切換到UDP。在這種情況下,您需要自己處理重傳。

澄清:

沖洗發送緩衝區通常會產生新的軟件包,就像你期望的那樣。如果您的客戶端讀取這些軟件包的速度足夠快,則可能每次讀取一條消息

現在想象你通過衛星鏈路進行通信。由於高帶寬和等待時間,坐在之前的最後一個路由器會等待一段時間,直到緩衝區中有足夠的數據並一次發送所有數據包。您的客戶端現在將立即收到所有數據包,並立即將所有數據放入接收緩衝區。所以你的分離再次消失了。

+0

+1:我會爲了edumacations的緣故添加,即使@Jah是刷新套接字,他的客戶仍然會收到完全相同的消息 - 刷新是關於以延遲減少名義清除緩衝區,以及*不*劃分消息。 – 2009-10-31 21:00:28

+0

給出了一個場景來說明這可能會出錯。 thx @ stu – ebo 2009-10-31 21:31:46

+0

+1:TCP是一個流。 TCP數據的時間通過互聯網路由和TCP協議被特別消除。數據必須緩衝; 「沖洗」實際上並不意味着太多。所有這一切意味着您的數據已經超出了您的應用程序的緩衝區並進入了TCP協議緩衝區。 – 2009-10-31 23:23:36

0

你正在試圖做的是將你的數據分成「批」。

例如,當您讀取文件中的「行」時,您正在對「批處理」進行操作。什麼定義了「線」?這是一個由'\ n'結尾的字節序列。另一個例子是:你從文件中讀取64KiB「塊」。什麼定義了「塊」?你這樣做,因爲你每次讀取65536字節。你想要一個可變長度的「塊」?你只需在你的「塊」前加上它的大小,然後閱讀「塊」。 「aiff」文件(其實現也是MS Windows的.wav和.avi文件)和「mov」文件就是這樣組織的。

這三種方法是組織字節流,無論媒體最根本的方法:

  1. 記錄分隔
  2. 固定大小記錄
  3. 記錄及其大小前綴。

它們可以混合和/或修改。例如,您可以像「XML讀取器」那樣擁有「變量記錄分隔符」:從第一個'<'讀取字節,直到第一個'>',在第一個'<'之後添加一個斜槓並將其稱爲結束記錄,讀取流直到最終的記錄。這只是一個粗略的描述。

選擇一種方法,並在作者和讀者中實現它。如果你還記錄你的選擇,你剛剛定義了你的第一個協議。

3

只是追加\ n每封郵件...... 像

socket.send後( 「頭1:MESSAGE1 \ n」)

socket.send( 「標題2:消息2 \ n」)

socket.send(「header3:message3 \ n」)

+1

這對我有用! – 2014-06-30 01:10:02

+0

「\ n」不保證郵件是分開的。 – crey4fun 2017-04-09 22:04:01