2014-05-21 34 views
1

我沒有看到如何增加一個上司的崩潰調用gen_tcp:聽線程實際上會重新啓動該名工人。由於崩潰會使我想在短時間內聽到無用的端口。當發生崩潰並且我試圖手動重新啓動我的應用程序時,我收到「{error,eaddrinuse}」。我還沒有爲這名工作人員實施任何監督,因爲我沒有看到它會如何工作。二郎OTP主管調用gen_tcp - {錯誤,EADDRINUSE}

如何重新啓動gen_tcp:listen?

+0

它有時甚至看起來像是如果套接字已關閉,端口仍在使用一段時間。不知道爲什麼。 – rvirding

+0

@rvirding - 顯然在插座上存在掛起連接的情況下。如果沒有掛起的連接,它應該立即進入CLOSED狀態。亞歷山大 - 請參閱Paul關於使用reuseaddr的回答,即使我的回答有幫助,哪個*應該用於您的服務器。 –

回答

0

管理gen_tcp socket的進程是gen_server嗎?如果是這樣,它會讓你的生活更輕鬆。

如果是gen_server,加process_flag(trap_exit, true)到您的初始化函數。這使得當你的進程「崩潰」時,它會在實際退出進程之前調用回調函數terminate/2。使用這種方法,您可以在terminate函數中手動關閉偵聽套接字,從而避免惱人的端口清理延遲。

如果你不使用gen_server,同樣的原則仍然適用,但是你必須更明確的瞭解捕捉你的錯誤。

+0

或者,您也可以在與「接受方」不同的過程中啓動監聽套接字。除了作爲套接字的存儲之外,所述進程應該不做任何事情,從而確保它永遠不會崩潰。這是可行的,因爲可以從多個進程同時調用'gen_tcp:accept'。 –

+0

感謝您的快速回復!我會嘗試添加陷阱,因爲我正在運行gen_server(應該提到這一點)。 關於分割接受/聽 - 如果我的應用程序崩潰,這將實際上足夠嗎? –

+0

如果整個應用程序崩潰,那麼即使您將責任分開,您也會遇到同樣的問題。但是,由於只需指定您真正需要它的trap_exit,並且在適當的時候允許您的客戶端進程正常崩潰,您仍然會受益。另外,請看看牧場(https://github.com/extend/ranch),它可以爲你處理很多這些東西。 –

1

在大多數情況下,由於監聽套接字連接到控制過程(創建它的過程),這個過程的終止將很好地關閉套接字,並允許您在同一端口上再次收聽。

對於所有其他情況下,你應該通過{reuseaddr, true}選項gen_tcp:listen/2。實際上,應用程序的偵聽套接字在崩潰後的一小段時間內保持活動狀態,並且此選項允許您在此期間重新使用該地址。

+0

reuseaddr的用途與您建議的不同。它確實可以用於這個目的,但如果使用不當,它也可能有令人討厭的副作用。 –

+0

reuseaddr正是阻止OP,是不可捕捉的崩潰所必需的。牧場也使用這個選項。 –

+0

reuseaddr的目的是允許服務器重新使用已經使用過的端口,是的,但是有更好的方法來解決這個問題,即正確清理終端上的監聽套接字,這也是ranch *確實。更好地使用reuseaddr適用於管理數千個短期客戶端的高容量服務器。 –