簡體   English   中英

一段時間后,寫入操作始終為連接的非阻塞套接字返回EAGAIN

[英]write always returns EAGAIN for connected nonblock socket after a while

我在ubuntu linux盒子上用c編寫客戶端服務器套接字程序。 服務器端需要處理許多連接,服務器和客戶端都具有本地套接字,以便在對其進行一些操作之后將接收到的數據發送到本地進程,並且發送和接收的數據數量巨大。 (數據大小不是很大,最大為1500)是下面的圖:
[客戶端的本地進程] <->數據<->客戶端<--------->服務器<->數據<-> [服務器的本地進程]

因此所有套接字(client_local_socket,client_remote_socket,server_remote_socket,server_local_socket)都必須是非阻塞的。

當我在局域網中的兩台計算機上運行客戶端和服務器時,它可以正常工作,但是當將服務器程序移至Internet中的linux服務器(客戶端連接到nat后面的服務器)時,客戶端開始與服務器成功通信(兩個客戶端)和服務器收到一些EAGAIN錯誤,但在下一次嘗試后恢復,並且我知道它對於非阻塞來說非常正常),但過了一會兒(超過1000個發送和接收數據包),client_remote_socket寫入錯誤代碼EAGAIN失敗,並且無法在下一次嘗試中恢復它,然后,它總是得到該死的EAGAIN進行寫入。 順便說一句client_remote_socket在讀取時沒有問題,並且始終從服務器獲取數據包。 服務器完全沒有問題,client_local_socket在寫入和讀取過程中都發揮作用。

我使用以下代碼使套接字成為非阻塞的:

int flags;
if ((flags = fcntl(client_remote_socket, F_GETFL, 0)) < 0)
    flags = 0;
flags = flags | O_NONBLOCK;
fcntl(client_remote_socket, F_SETFL, flags);

我也嘗試過:

fcntl(client_remote_socket, F_SETFL, O_NONBLOCK);

但是結果是一樣的。

我使用的唯一setsockopt是服務器端的SO_REUSEADDR,而客戶端沒有setsockopt。

值得一提的是,我總是檢查write返回的值,當它小於0時,我檢查errno並查看其EAGAIN。 據我所知,當內核沒有用於寫緩沖區的可用空間,並且在具有4 GB內存的筆記本電腦中內核對我沒有內存時,寫操作將返回EAGAIN。 當我在局域網中同時運行客戶端和服務器時,BTW可以正常工作。 當這種情況在客戶端中發生時,服務器不會顯示客戶端套接字損壞的任何跡象,這是正確的,因為與此同時,它可以從服務器接收數據。 我一遍又一遍地檢查了代碼,並嘗試對其進行多次調試,沒有發現任何錯誤。 我還使用了select系統調用來檢查套接字是否可用於寫入,並且當時間到來時總是返回0。 現在我不知道要解決這個問題,任何想法對我來說都會非常感激。 謝謝。

上周我遇到了同樣的問題,經過研究后,我發現這是因為對等方的緩沖區已滿。 我測試了這種情況。

當遠程緩沖區已滿時,它告訴您的本地堆棧停止發送。 當從遠程緩沖區中清除數據(通過由遠程應用程序讀取)時,遠程系統將通知本地系統發送更多數據。

這是布萊恩·懷特的答案https://stackoverflow.com/a/14244450/3728361

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM