2011-11-21 52 views
1

我正在編寫一個簡單的基於UDP的客戶端/服務器應用程序,並在localhost上測試客戶端/服務器,我希望發件人知道send()何時會被阻止。我使用Python,所以我覺得我可以做的:如何獲得send()以阻止UDP?

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
s.setblocking(0) 
s.connect(('127.0.0.1', 12345)) 
data = "x" 
for i in range(0, 9000): # More than about 9000 gives an error 
    data += x 
while True: 
    try: 
     s.send(data) 
    except socket.error as e: 
     print "Would have blocked" 
     # Do something useful here 

我想測試我的錯誤處理代碼的工作,所以我想獲得發送()想要封鎖。問題是,我無法弄清楚如何做到這一點。我試過了:

BUFFSIZE = 2000 
input = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
input.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, BUFFSIZE) 
input.bind(('127.0.0.1', 12345)) 
while True: 
    data = input.recv(BUFFSIZE) 
    time.sleep(100) 

在睡眠100秒和設置一個小的接收緩衝區之間,我會預期緩衝區已經填滿了。但是,它從來沒有。那麼如何讓接收緩衝區填滿以便發送數據塊?

我正在使用Mac OS Lion和Macports版本的Python 2.6。

回答

4

UDP通常不會阻塞。如果接收器有一個完整的緩衝區,數據包將被默默丟棄。這是設計。如果您想要可靠的傳輸和阻塞語義,請改用TCP。

評論: TCP塊的原因是因爲發件人得到了它發送的每個數據包的確認。發件人只允許「傳輸中」的一定數量的沒有確認的數據,並在達到此閾值時阻止。由於UDP不發送收到的數據包的確認,因此發送者無法知道何時阻止。當然,如果它的以太網端口飽和,它可能會決定阻塞,但是使用UDP則無法確定上行鏈路是否飽和,接收器是否掛起,或者gremlins是否吃掉了您的數據包。沒有保證!

+0

發件人沒有得到每個TCP數據包的確認。它現在實際上獲得選擇性ACK,並且僅適用於當前接收窗口內的那些*段*。接收器確實承認*字節,*不包。可以傳輸的未確認數據量由套接字發送緩衝區大小定義。換句話說,當發送緩衝區已滿時,發送方會阻塞它。 – EJP

+0

我意識到UDP是不可靠的,並沒有問題。這是我所擔心的「不正常的區塊」。我如何創建非正常的情況下阻止?從你的評論,幾乎只有在上行鏈路飽和的情況下(假設操作系統決定不放棄它)? – prewett

+0

@EJP:道歉,我的語言sl。。 –