2013-11-25 77 views
1

我曾在非阻塞式TCP中工作,因爲在非阻塞情況下,讀取和寫入都會失敗。如果沒有數據可用,TCP非阻塞讀取可能會失敗,如果對端TCP緩衝區已滿(我希望TCP緩衝區大小爲64K),TCP寫入可能會失敗。UDP非阻塞式寫入失敗

類似地,如果沒有可用的數據,UDP讀取(recvfrom)可能會失敗。但是,UDP寫入失敗的情況是什麼(sendto)。我認爲在UDP寫入時不會有任何非阻塞錯誤。因爲TCP寫入發送數據並等待來自另一端的ACK。但是,UDP寫入並不是這樣,它只會發送出去,並且不會等待來自對端的任何ACK。如果不發送給其他方意味着其丟包。

我對UDP非阻塞寫入的理解是否正確?請解釋 ?

+0

可能有很多原因。你是否在寫入失敗時檢查了errno的價值? –

回答

8

UDP非阻塞發送失敗的最可能原因是UDP套接字的內核傳出數據緩衝區已滿。在這種情況下,send()/ sendto()將返回-1,errno將被設置爲EWOULDBLOCK。

請注意,非阻塞send()/ sendto()在返回之前並不實際將數據發送出網絡設備;而是將數據複製到內核緩衝區中並立即返回,此後內核負責將數據儘可能快地移出網絡。如果程序嘗試一次發送大量數據,則傳出數據緩衝區可能會變滿,因爲CPU可以將新數據添加到緩衝區,速度比網絡硬件可以將緩衝區數據轉發到網絡的速度快得多。

如果您得到-1/EWOULDBLOCK錯誤,通常處理它的最優雅的方式是停止嘗試發送該套接字,直到套接字select()(或poll()或等)準備好寫。發生這種情況時,您知道內核緩衝區至少已部分耗盡,您可以再次嘗試send()/ sendto()調用。

如果您嘗試發送的IP地址無效,另一個(不太可能)導致send()錯誤的原因是。無論如何,你應該檢查errno並找出errno值是什麼,因爲這可以讓你更好地瞭解發生了什麼問題。

順便說一句,上面描述的行爲對於UDP來說並不是唯一的;如果您嘗試在套接字上發送()數據的速度比本地網卡可能耗盡套接字的內部速度更快,則您可以並且將與非阻塞TCP套接字(即使遠程對等方的接收窗口未滿)內核緩衝區。

1

由於TCP寫入發送數據並等待來自對方的ACK。

不,它不。它的數據複製到套接字發送緩衝區,如果已滿,要麼阻止或返回-1/EWOULDBLOCK/EAGAIN.

但這不是UDP的情況下寫它只會發送和出來和它不等待任何ACK來自同伴。

不,它不。它將您的數據複製到套接字發送緩衝區中,如果該數據已滿,則它將阻止或返回-1/EWOULDBLOCK/EAGAIN.

在這兩種情況下,實際將字節放到線路上都與您的程序異步。