2013-02-06 53 views
1

我已經通過Ubuntu Linux內核3.5.0-23編寫了epoll服務器,在一個問題上運行得很好:如果客戶端連接,然後註銷,我可以立即重新啓動服務器。但是,如果客戶端仍然連接並關閉服務器,他將斷開連接,但端口仍然會被綁定X秒(不能告訴X,我會說大約20)。 如果我正在用編譯器終止程序,這也會發生。epoll服務器不會解除綁定

當關閉時,我使用的是當客戶離開我使用的是完全相同的功能:

int CEpollClient::Close() 
{ 
    if(m_socket!=SOCKET_ERROR) 
    { 
    int res=::epoll_ctl (m_server_handler, EPOLL_CTL_DEL, m_socket, 0); 
    _debug_message("client exits"); 
    _debug_message(res); 
    shutdown(m_socket,SHUT_RDWR); 
    ::close (m_socket); 
    m_socket=SOCKET_ERROR; 
    } 
    return 0; 
} 

這是客戶端類的一部分,所以這完全一樣的代碼被稱爲我是否」在他離開或自己初始化之後關閉客戶端。 關閉服務器的時候我也正在關閉監聽套接字:

if (m_listener != SOCKET_ERROR) 
{ 
    _debug_message("stop listener"); 
    code=epoll_ctl(m_epoll_handler,EPOLL_CTL_DEL,m_listener,0); 
    _debug_message(code); 
    shutdown(m_listener,SHUT_RDWR); 
    ::close(m_listener); 
    m_listener = SOCKET_ERROR; 
} 

有人能提供什麼想法?這並不可怕,而且可行,但它確實看起來像一個bug。 調試消息中的返回碼始終爲0 - 無錯誤。 那麼爲什麼會發生?

回答

1

你提出的問題不是epoll相關,而是socket相關。您無法重用該套接字的原因是,它仍然處於TCP TIME_WAIT狀態。這是正常的行爲,通過設計。延遲通常是最大段壽命的兩倍,以確保在任何情況下都可以執行完整的往返執行正確關閉,但也可以使用SO_LINGER進行配置。你可能會試圖簡單地配置SO_LINGER更短的時間,但不要這樣做。使用此撥號不建議,因爲它可能會干擾正常,正常關機。

另一個選項是設置SO_REUSEADDR套接字選項,這可能是你想要的。請注意,SO_REUSEADDR告訴套接字層忘記其所做的正確性承諾,並故意破壞正常的可操作性。基本上你在告訴你的網絡庫:「是的,我知道這樣做是不對的,但我保證沒有人會在意這個套接字,並且不會發生任何惡事。」
你的例子中就是這樣的情況。你已經很難關閉套接字了,它已經消失了,沒有其他人使用它了,你所關心的是儘快重新使用套接字。

有關可用套接字選項的說明,請參閱socket(7)

+0

雖然這個鏈接可能回答這個問題,但最好在這裏包含答案的基本部分並提供參考鏈接。如果鏈接頁面更改,則僅鏈接答案可能會失效。 –

+0

@AndyKorneyev:k.o.的回答仍然是所有相關信息的焦點(儘管沒有最佳解釋)。我會看看我是否可以編輯以使其更清晰。 – Damon