0

次の固有の要件を持つクライアント サーバーの問題があります。 1. サーバーは既知のクライアントに対して N 個の接続を開く必要があり、クライアントはそれらの接続を使用してサーバーからデータを要求することしかできません。

これまでのところ、次のことを試みましたが、いくつかの問題に遭遇しました。

  1. クライアントにソケット リスナーを用意し、受信した各接続を ArrayBlockingQueue にエンキューします。

  2. クライアント アプリは、上記のキューで利用可能な接続を使用して、サーバーからデータを要求します

  3. サーバー上のソケットごとに 1 つのスレッド (ワーカー) を作成し、N 個のワーカー スレッドを介してデータ要求をリッスンします。

  4. ワーカー スレッド (サーバー上) で着信要求を待機するときは、InputStream.isAvailable() を使用して、読み取りを待っているものがあるかどうかを確認します。

問題: サーバー側のワーカー スレッドは、ソケット接続がまだ有効かどうかを認識していませんか? クライアントアプリでソケットが閉じられた後でも、リクエストをリッスンし続けます。

ソケット接続がまだ有効かどうかをサーバーに認識させるにはどうすればよいですか?

ここで正しいアプローチを取っていますか?

実装をより簡単に、より良くするフレームワークはありますか?

4

4 に答える 4

1

質問に netty のタグを付けました。Nettyを使ってみましたか?いずれにせよ、私はそれをお勧めします。

  • クライアントは ServerBootstrap/ServerSocketFactory と適切なチャネル パイプラインを使用する必要があります。Netty には、BlockingQueue の代わりに使用できる ChannelGroup の概念が既にあります。クライアント コードは、グループを反復処理して空きチャネルを削除する (そして完了したら元に戻す) ことで、空きチャネルを見つけることができます。また、チャネル グループは、閉じられたチャネルを自動的に検出し、それ自体から削除します。
  • サーバーは ClientBootstrap/ClientSocketFactory と、クライアント要求に応答するハンドラーを備えた適切なチャネル パイプラインを使用します。
  • 通常の TCP クローズ操作が検出され、チャネルがクローズされます。クライアントが「クラッシュ」して反対側が途方に暮れることが懸念される場合、Netty には IdleStateHandler があり、一定期間非アクティブになった後にチャネルを閉じることができます。
于 2013-04-15T15:54:51.880 に答える
1

プロトコルを逆にしてみませんか?

  • クライアントが接続を開始します
  • サーバーはそれらを承認します(既知のクライアントのみを許可します)
  • 次に、サーバーはデータを受信/クライアントにプッシュし、確認を受信できます
  • 接続が失われた場合、クライアントは再開できます (サーバーは各クライアントに送信されたデータを追跡し、再接続時に失われたデータを再送信できます)。
于 2013-04-15T15:09:25.377 に答える
0

ワーカー スレッド (サーバー上) で着信要求を待機するときは、InputStream.isAvailable() を使用して、読み取りを待っているものがあるかどうかを確認します。

InputStream.isAvailable()接続がピアによって閉じられたかどうかはわかりません。read()接続が閉じられているかどうかを確認するには、呼び出す必要があります。

を使用する必要がInputStream.isAvailable()ある場合は、少なくとも に定期的に何かを書き込む必要があります。そうすれば、接続が閉じOutputStreamられたことを示す が得られます(たとえば)。IOExceptionconnection reset by peer

于 2013-04-16T08:07:02.330 に答える