2010-10-18 67 views
4

在兩臺主機之間使用udp中的非阻塞讀取時,丟失消息時出現問題。發件人在Linux上,讀者在winxp上。 python中的這個例子顯示了這個問題。
以下是用於顯示問題的三個腳本。
send.py使用非阻塞udp讀取時丟失消息

import socket, sys 
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) 
host = sys.argv[1] 
s.sendto('A'*10, (host,8888)) 
s.sendto('B'*9000, (host,8888)) 
s.sendto('C'*9000, (host,8888)) 
s.sendto('D'*10, (host,8888)) 
s.sendto('E'*9000, (host,8888)) 
s.sendto('F'*9000, (host,8888)) 
s.sendto('G'*10, (host,8888)) 

read.py

import socket 
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
s.bind(('',8888)) 
while True: 
    data,address = s.recvfrom(10000) 
    print "recv:", data[0],"times",len(data) 

read_nb.py

import socket 
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
s.bind(('',8888)) 
s.setblocking(0) 
data ='' 
address = '' 
while True: 
    try: 
     data,address = s.recvfrom(10000) 
    except socket.error: 
     pass 
    else: 
     print "recv:", data[0],"times",len(data) 

實施例1(工程確定):

的ubuntu>蟒send.py
WINXP>read.py

給從read.py此OK結果:

的recv:A倍10
的recv:B乘以9000
收件人:C次9000
收件人:D次10
收件人:E次9000
收件人:F次9000
的recv:3G時代10

實施例2(丟失消息):在這種情況下
短消息通常不會通過read_nb.py 被獲取,我給它如何可以像兩個例子。

的ubuntu>蟒send.py
WINXP>read_nb.py

給從read_nb這個結果。PY:

的recv:A倍10
的recv:B乘以9000
的recv:C倍9000
的recv:d次10
的recv:E時代9000
的recv:F倍9000

以上是最後10字節的消息丟失

下面

在中間缺失

再一個10字節的消息CV:A倍10
的recv:B乘以9000
的recv:C倍9000
的recv:E時代9000
的recv:F倍9000
的recv:3G時代10

我已使用Wireshark上檢查窗口和每次捕獲所有消息,以便它們到達主機接口,但不被read_nb.py捕獲。什麼是解釋?

我也試圖與在Linux和send.py在Windows read_nb.py,然後它的作品。 所以我認爲這個問題與winsock2

或者也許我正在使用非阻塞udp錯誤的方式?

回答

4

丟失消息是正常的UDP - 傳輸層不保證順序或數據包的傳送。如果您希望它們按順序和/或始終交付,請切換到TCP或自己執行排序和/或確認/超時/重新傳輸。

要將例子 - 大消息是較大的,然後在1500個減去八個字節的UDP頭的正常以太網MTU(除非您使用巨型幀),並因此將由發送方進行分片。這給發送者和接收者都帶來了更多的負擔,但是對接收者的影響更大,因爲它需要在內核內存中保留片段,直到完整的數據報到達。

我懷疑你的接收緩衝區溢出36030字節,但我從來沒有在Windows上進行網絡連接,所以你最好在接收器上檢查SO_RECVBUF套接字選項的值,如@Len所示。

同時檢查的netstat -s輸出看到被丟棄的包數。

+1

窗口:s.getsockopt(socket.SOL_SOCKET,socket.SO_RCVBUF)= 8192個字節。 ubuntu:buf = 112640 bytes – lgwest 2010-10-19 15:45:42

+0

好的,這是問題所在。很高興知道。 – 2010-10-19 16:35:25

+1

嗯,所以我建議的解決方案和尼古拉得到的答案,沒有公正:( – 2010-10-19 17:16:56

6

如果數據報到達主機(就像你的wireshark日誌顯示的那樣),那麼我看的第一個地方就是你的套接字recv緩衝區的大小,使它儘可能大,並且運行速度與你一樣快能夠。

當然這是UDP完全可以預料的。您應該認爲數據報可以在任何時候被丟棄,並且出於任何原因。此外,如果你需要的可靠性,那麼你需要建立自己的,或者使用TCP你可能會得到數據報不止一次......

+0

這裏的+1和正義爲你:) – 2010-10-19 17:21:25