我正在寫一個客戶端服務器套接字程序在c上的一個Ubuntu的Linux機器上。 服務器端需要處理多個連接,並且服務器和客戶端都有一個本地套接字,用於在接收到的數據經過處理後發送到本地進程,並且發送和接收的數據量很大。 (數據的大小也不是很巨大的,最大1500) 這裏是圖:
[客戶端的本地進程] < - >數據< - >客戶端< --------->服務器< - >數據<→[本地進程服務器]一段時間後寫入總是返回EAGAIN連接的非阻塞套接字
所以所有的套接字(client_local_socket,client_remote_socket,server_remote_socket,server_local_socket)都需要是非阻塞的。
當我在LAN網絡中的兩臺計算機上運行客戶端和服務器時,它工作得很快,但是當將服務器程序移動到互聯網上的Linux服務器時(客戶端連接到服務器後面的nat),客戶端開始與服務器(客戶端和服務器都會得到一些EAGAIN錯誤,但在下次嘗試後恢復它,因爲我知道非阻塞非常正常),但過了一會兒(超過1000個發送和接收數據包),client_remote_socket寫入錯誤代碼失敗EAGAIN,無法在下一次嘗試中恢復它,之後,它總是得到這個該死的EAGAIN的寫作。 BTW 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。
它不錯,我總是檢查寫回報的價值,當它是< 0我檢查errno,看看它的EAGAIN。 據我所知,當內核沒有可用空間用於寫入緩衝區時,寫入將返回EAGAIN,並且在4 GB RAM的筆記本電腦中內核對我而言沒有任何意義。並順便說一句,當我在LAN網絡中運行客戶端和服務器時,它工作得很順利。 當客戶端發生這種情況時,服務器不會顯示任何損壞的客戶端套接字及其正確的標誌,因爲與此同時,它可以從服務器接收數據。我再次檢查了一遍又一遍的代碼,並嘗試多次調試,並且看不到任何錯誤。我還使用select系統調用來檢查套接字是否可用於寫入,並在時間到時始終返回0。 現在我不知道解決這個問題,任何想法都會對我非常感興趣。 謝謝。
我沒有看到你有很多選擇,但張貼相關的代碼的答案。 – Duck
套接字無法使用所有內存,套接字緩衝區有限制,通常高達幾MB。獲得EAGAIN是100%正常的,通常意味着網絡無法處理更多流量,或者接收應用程序接收速度不夠快。 – nos
令我感到棘手的感覺是,在第一段中,你說「服務器端需要處理多個連接」,最後是「我也使用了選擇系統調用」,顯然作爲調試機制而不是處理許多連接的必要條件。如果你只是在一個循環中衝擊'send',那麼獲得大量的EGAIN並不奇怪。 – Duck