2011-10-03 79 views
17

我有一個由主服務器和分佈式從服務器組成的程序。從服務器向服務器發送狀態更新,如果服務器在固定時間內沒有收到特定的從服務器的響應,則會將從服務器標記爲關閉。這一直在發生。無法分配請求的地址 - 可能的原因?

從檢查日誌,我發現從站只能發送一個狀態更新到服務器,然後永遠不能發送另一個更新,總是失敗的通話連接()「無法分配請求的地址(99)

奇怪的是,從服務器能夠向服務器發送幾個其他更新,並且所有的連接都在同一個端口上發生,看起來這種故障的最常見原因是連接是還有其他可能的解釋嗎?

爲了澄清,這裏是我如何連接:

struct sockaddr *sa; // parameter 
size_t   sa_size; //parameter 
int    i = 1; 
int    stream; 

stream = socket(AF_INET,SOCK_STREAM,0); 
setsockopt(stream,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(i)); 
bindresvport(stream,NULL); 
connect(stream,sa,sa_size); 

此代碼位於一個函數中,用於獲取與另一個服務器的連接,並且這四個調用中的任何一個失敗都會導致該函數失敗。

+0

我已經驗證了端口和ip地址都是正確的。 – dbeer

回答

9

也許SO_REUSEADDR在這裏有幫助嗎? http://www.unixguide.net/network/socketfaq/4.5.shtml

+0

SO_REUSEADDR爲所有連接設置。 – dbeer

+1

這裏有一個類似的:http://stackoverflow.com/questions/3886506/why-would-connect-give-eaddrnotavail – dmh2000

+0

@ dmh2000 - 我在發佈之前看過這個例子,並沒有試圖成功研究這些因素。我想知道如果我只是需要繼續看,或者有什麼我沒有考慮到。 – dbeer

3

這僅僅是一個在黑暗中拍攝:當你調用連接而無需綁定第一,系統分配的本地端口,如果你有連接和斷開它可能嘗試已經分配一個端口多線程使用。內核源文件inet_connection_sock.c提示此情況。就像實驗嘗試先綁定本地端口一樣,確保每個綁定/連接使用不同的本地端口號。

+0

我會試試看看它是否有幫助 – dbeer

+0

對不起,我發佈時沒有看到我的代碼。我在連接之前調用綁定。我會更新我的問題以更好地展示我在做什麼。 – dbeer

5

事實證明,問題確實是地址繁忙 - 繁忙是由於我們處理網絡通信的一些其他問題導致的。你的投入幫助我弄清楚了這一點。謝謝。

編輯:具體來說,處理我們的網絡通信的問題是,如果第一次失敗,這些狀態更新將不斷重新發送。直到我們讓每個分佈式從機試圖同時發送其狀態更新,這只是一個時間問題,這是過度飽和我們的網絡。

+0

如果在我自己的代碼中出現同樣錯誤的原因,我會喜歡對「繁忙」進行闡述 - 您的意思是「服務器接受連接的套接字隊列等待accept()以等待另一個連接被允許放在隊列中?「或者是另一種情況?謝謝! –

+2

@BrandonRhodes我們的問題是,我們有一些重試發生沒有​​適當的退避算法,所以我們每秒鐘有數百個或更多的連接嘗試到同一個套接字。這個爭論導致了我們的失敗。實施適當的退避算法對解決這個問題至關重要。 – dbeer

+0

感謝您的額外信息!很高興你修好了它。 –

1
sysctl -w net.ipv4.tcp_timestamps=1 
sysctl -w net.ipv4.tcp_tw_recycle=1 
+3

你如何撤銷這2個? – ado

+6

沒有解釋這個答案沒有任何價值。 –

相關問題