2013-04-15 96 views
0

我有一個客戶端服務器問題,具有以下獨特要求: 1.服務器必須打開已知客戶端的N個連接,並且客戶端只能使用這些連接來請求數據服務器。Java套接字:打開從服務器到客戶端的連接

到目前爲止,我試着做以下,但遇到了一些問題:

  1. 在客戶端上的套接字監聽器,並把它接收到一個ArrayBlockingQueue排隊的每個連接。

  2. 客戶端應用將使用在隊列中可用連接到上述請求數據從服務器

  3. 我在服務器上創建每個插槽一個線程(工人)和監聽到N工作線程的數據請求。

  4. 當我在工作線程中等待傳入請求時(使用服務器)我使用InputStream.isAvailable()來檢查是否有等待讀取的內容。

問題:服務器端的工作線程不知道套接字連接是否仍然存在或不存在?即使在客戶端應用程序關閉套接字後,它們仍繼續監聽請求。

如何讓服務器感知套接字連接是否仍然存在?

我在這裏採取正確的方法嗎?

是否有一個框架,將使實施更容易和更好?

+0

關閉時發送消息到服務器。或者,使所有連接在特定級別的不活動之後超時?我相信這會自動發生,但您也可以設置顯式超時。 – Sanchit

+0

您引用的問題不存在。客戶端關閉時服務器將讀取EOS。 – EJP

回答

1

你爲什麼不反轉協議?

  • 您的客戶將啓動連接
  • 你的服務器將授權他們(只允許已知客戶端)
  • 那麼你的服務器可以接收/數據推送到客戶端,並收到確認
  • 如果連接丟失,客戶端可以重新啓動(服務器可以跟蹤哪些數據已發送到每個客戶端,並在重新連接時重新發送丟失的數據)
+0

感謝您的快速響應。不幸的是,只有服務器應該啓動連接是一項要求(安全性)。 – user851894

+0

@ user851894這是一個完全不好的想法,但這是所有要求的常見故事:) – gaborsch

1

您已經標記了questio n與netty。你有沒有嘗試過使用Netty?無論哪種情況,我都會推薦它。

  • 您的客戶端應使用ServerBootstrap/ServerSocketFactory和適當的通道管道。 Netty已經有了一個可以用來代替BlockingQueue的ChannelGroup概念。您的客戶端代碼可以通過遍歷該組找到免費頻道並刪除免費頻道(並在完成時將其放回)。頻道組也會自動檢測封閉的頻道並將其從本身中刪除。
  • 您的服務器將使用一個ClientBootstrap/ClientSocketFactory和一個適當的通道管道,並具有響應客戶端請求的處理程序。
  • 正常的TCP關閉操作將被檢測到,通道將被關閉。如果您關注的是客戶「撞車」和葉在地獄的另一端,Netty中有一個IdleStateHandler能閒置一段時間後關閉通道
+0

我快速瀏覽了一下,但不確定如何將它用於我的用例。我會嘗試並讓你知道。感謝你的幫助。 – user851894

0

問題:在服務器端不要工作者線程不知道套接字連接是否仍然存在?

是的,他們這樣做。當客戶端關閉連接時,他們將讀取EOS。那裏沒有問題。

即使在客戶端應用程序關閉套接字後,它們仍會繼續偵聽請求。

只有當您忽略了EOS條件。

如何讓我的服務器感覺如果套接字連接仍然存在或不存在?

如果讀取EOS時關閉套接字並停止讀取循環。

我在這裏採取正確的做法嗎?

您的問題描述是回到前面。客戶端創建與服務器的連接,而不是相反。

+0

對不起,如果我不夠清楚。 1.僅使用isAvailable()就不可能檢測到斷開連接。是的,如果我讀了,我將能夠感覺到它。根據你的建議,我應該逐字節閱讀嗎? 2.不幸的是我的要求(安全)是隻有服務器應該發起連接。如果不是這個要求,那麼解決起來會非常簡單。 – user851894

+0

當您需要閱讀並處理EOS時,您應該閱讀它。 available()不是EOS測試,並且幾乎沒有其他有效用途。您的要求是濫用標準術語。您的服務器是客戶端,您的客戶端是從TCP角度來看的服務器。 – EJP

+0

對,直到建立連接,服務器和客戶端的角色纔會顛倒過來。 – user851894

0

當我在工作線程中等待傳入請求時(使用服務器)我使用InputStream.isAvailable()檢查是否有東西在等待讀取。

InputStream.isAvailable()永遠不會告訴對方是否已關閉連接。您必須致電read()檢查連接是否已關閉。

如果必須使用InputStream.isAvailable(),你必須至少定期寫一些東西到OutputStream,那麼你會得到一個IOException,指示該連接已關閉(connection reset by peer爲例)。

+0

對,我的客戶端上有一個HeartBeatSender和一個工作線程(HeartBeatListener),專門用於收聽心跳信號?如果我有一段時間沒有心跳,我可以用新的套接字連接重新設置N個工作線程。 – user851894

相關問題