2010-12-29 10 views
2

単体テストを実装するには、単純なクライアントとサーバー間の通信が必要です。ServerSocket accept()がソケットを "listen"モードにするのを待つ

マイ手順:

  1. 確認し、いくつかのリクエストを行い、クライアント
  2. を作成リッスンモード(serverSocket.accept())にサーバソケットを置くために、サーバースレッドのサーバースレッド
  3. 待ち
  4. を作成します。応答

基本的に、私はステップ#2に問題があります。私は、サーバーソケットが "listen"状態になったときに私に信号を送る方法を見つけることができません。この場合、 "accept"への非同期呼び出しが行いますが、javaはこれをサポートしていません(非同期チャネルのみをサポートしているようですが、ドキュメントに従って "accept()"メソッドと互換性がありません)。

私は単純な「スリープ」を入れることができますが、それは実際にはプロダクションコードの解決策ではありません。

要約すると、ServerSocketがスリープおよび/またはポーリングを使用せずにリッスンモードに入ったときを検出する必要があります。

答えて

5

ServerSocketオブジェクトを構築するとすぐにソケットがリスニング状態になります。acceptを呼び出すときではありません。 ServerSocketコンストラクタが完了した後でクライアントを作成する限り、問題は発生しません。接続は受け入れられ、acceptが呼び出されるまで内部的にキューに入れられます。

がここに実証するためのいくつかのコードされています

ServerSocket serverSocket = new ServerSocket(12345); 
Thread.sleep(10000); 
Socket socket = serverSocket.accept(); 

を、10秒間隔の間にaccept前に呼び出され、OSのnetstatコマンドは「LISTENING」状態のサーバソケットが表示され、クライアントはそれに接続することができます。その10秒間にクライアントが接続すると、接続はキューに入れられ、acceptメソッドが最後に呼び出されると、すぐにキューに入れられたSocketオブジェクトが返されます。

+0

はい、あなたは正しいです。その奇妙なドキュメントはそれについて何も言わない。しかし、それはおそらくその実装固有の(またはTCPプロトコルのみに固有の)ためです。 – inazaruk

+0

@inazarukドキュメントは、いくつかの場所でバックログのキューについて語っています。 – EJP

-1

なぜaccept()を呼び出す直前にsingleを送信しないのですか?

connectionAccepted = true; 
loc.notify(); 
socket.accept(); 

ソケットがあなたの「クライアント」のコードに小さな睡眠を追加する準備ができていることを確認する:

wait(); 
// we are here when notify is called. 
Thread.sleep(10); // 10 ms 
startTest(); 

あなたも、より良い行うことができますへの「ピング」ソケットと試みるループを作成します試行の間に小さな睡眠。この場合、可能な限り迅速にテストを開始します。

+0

このソリューションは、単純なsleep()と同じ問題があります。スリープが切れた後、サーバーソケットがリッスンモードに入ることは保証されません。確率は単純なsleep()を使うよりも高いですが。 – inazaruk

+0

ネットワークコードにスリープ状態を追加しても問題は解決しません。それはそれらを遅らせるだけです。 – EJP

関連する問題