2017-04-23 63 views
0

我有一個客戶端服務器應用程序。當多個客戶端連接到指定的端口上的服務器說6001,我面臨一個問題。問題是當客戶端連接到服務器,並且如果我使用命令kill -9 $ pid(其中pid是服務器應用程序pid)使用腳本停止服務器,則在重新啓動服務器時,我會得到一個BIND異常地址這意味着由於哪些客戶端無法連接到服務器,端口6001仍然不可用於客戶端再次連接。在客戶端服務器應用程序中動態選擇連接端口

我正在尋找解決這個問題的方法。我有一個動態使用端口範圍的想法。

這裏是我的想法:

在XML文件,而不是硬編碼端口號爲6001,我將提供一系列的端口說6001-6005。然後,當服務器啓動時,它將循環通過端口來選擇可用的端口。例如 - 當服務器嘗試創建綁定到指定端口6001的服務器套接字時,如果存在例外情況,即如果端口已被另一個應用程序綁定,則它將選擇6002端口等。無論哪個端口可用,服務器都會爲其創建服務器Socket對象,並開始監聽該端口上的客戶端。

現在同樣在客戶端,它將首先嚐試在6001上連接,如果失敗,則連接到6002等,直到它連接到服務器正在偵聽的正確端口。

我的問題是如果這是正確的做法。另外,如果客戶端可以以上述方式連接。

如果否,那麼是否有任何解決上述問題的方法。

+0

如果您成功終止程序,端口應該可用。您的代碼是否啓動處理傳入連接的子進程?如果是這樣,那個子進程仍在運行? –

+0

好吧,我不確定是否有其他進程在運行。我如何找到?我的服務器在Solaris上運行。這個問題不會在Linux上覆制,也不在Windows上覆制。你能否提供一個可以殺死所有進程的命令,包括子進程? 下面是停止服務器時運行的命令。 # #關閉服務器 # kill_server(){ PID ='server_pid' 如果[ 「$ PID」!=「」];然後 /bin/kill -9 $ pid echo服務器已停止。 else echo服務器未運行。 fi } –

回答

0

要查找使用一個端口使用

lsof的-wni TCP進程的PID:端口號

然後採用pid它會釋放出端口進一步使用殺死進程,它不會給「已在」使用錯誤。這將解決您的問題。更好的做法是擁有一個從客戶端訪問的單一端口。

+0

我正在使用Solaris。我認爲這個命令不適用於solaris。你知道solaris的命令嗎? –

+0

請參閱在solaris中討論關於lsof等效腳本的鏈接http://stackoverflow.com/questions/20670400/equivalent-lsof-i-in-solaris – OTM

1

您需要創建ServerSocket這樣的:

ServerSocket ss = new ServerSocket(); // NB no parameters 
ss.setReuseaddress(true); 
ss.bind(new InetSocketAddress(port)); 

這告訴操作系統它的確定到服務器綁定套接字即使在TIME-WAIT狀態,此狀態轉移的連接。如果仍然有一個應用程序的先前實例正在運行,那麼您需要先停下來。

忘記端口範圍的東西。

+0

ss.bind(port);或者ss.bind(新的InetSocketAddress(端口)); ? 另外,ss.bind有什麼用?如果我只是使用setReuseAddress? 順便thanx爲您的迴應! –

+0

是的,'bind(new InetSocketAddress(port))'。 'setReuseAddress()'應該*在* bind()之前,並且不能替代它。 – EJP