2017-12-21 10 views
1

私のタイトルはおそらく最も記述的ではありませんが、皆さんが私の質問をよりよく理解できるようになるためにできるだけ多くのコードを表示していきます。私のプロジェクトのクライアント側がサーバーに情報を問い合わせる方法は次のとおりです。これは典型的な要求の例である:他のリクエストをブロックせずにソケット入力を聞く方法

private String GENERATEGROUPKEY() 
{ 
    /* `out` is a PrintWriter using the sockets output stream */ 
    out.println("GENERATEGROUPKEY"); 

    try 
    { 
     /* `in` is a BufferedReader using the sockets input stream */ 
     String response = in.readLine(); 
     String[] temp = response.split(" "); 

     return temp[1]; 
    } 
    catch (IOException ex) 
    { 
     return null; // throw connection error to client 
    } 
} 

私の問題は、任意の時点で、サーバは情報とその同じソケットを介してクライアントに迷惑メッセージを送ることができるということである(受信チャットクライアントのようにそれについて考えますメッセージ)。私の失敗した考えは、別のクエリの途中でない限り、このようなメッセージを聞くスレッドを作成することでしたが、それは失敗しました。なぜなら、そのスレッドを中断していても、クライアントのクエリに行きました。ここで

private String GENERATEGROUPKEY() 
{ 
    out.println("GENERATEGROUPKEY"); 
    listenThread.interrupt(); // block listenThread from recieving response 

    try 
    { 
     String response = in.readLine(); 
     String[] temp = response.split(" "); 

     listenThread = new PulseThread(in); // we're done, so allow 
     listenThread.start(); 
     return temp[1]; 
    } 
    catch (IOException ex) 
    { 
     listenThread = new PulseThread(in); // we're done, so allow 
     listenThread.start(); 
     return null; // throw connection error to client 
    } 
} 

listenThread私はBufferedReaderの途中でスレッドを中断し「私がない限りreadLine()での着信拒否するだけでブロッキング呼び出しをキャンセルするだろう」という印象の下に以前だっ

public class PulseThread extends Thread 
{ 
    private BufferedReader in; 

    public PulseThread(BufferedReader in) 
    { 
     this.in = in; 
    } 

    @Override 
    public void run() 
    { 
     while (true) 
     { 
      if (Thread.currentThread().isInterrupted()) 
      { 
       break; 
      } 
      try 
      { 
       String line = in.readLine(); 
       System.out.println(line); 
       String[] params = line.split(" "); 
       if (params[0].equals("PULSED")) 
       { 
        NotificationManager.sendNotification("You have been pulsed!", "Pulsed by: " + params[1]); 
       } 
      } 
      catch (Exception ex) 
      { 

      } 
     } 
    } 
} 

ですまさにです他の何かを間違ってやっている。

ご協力いただきありがとうございます。

EDIT:この文章の上にほんの数行だけ私の前提を見て、スレッドを中断していると思われます。readLine()。私は中断スレッドのアイデアはないと思う。これを行う正しい方法は何ですか?

+0

あり、エラー:[タグ:マルチスレッド]?そして、スレッドを中断すると、ブロックされているI/O操作が取り消されるということはどこからですか? – EJP

+0

@EJPこれはマルチスレッドの質問ではありませんか?正当でユニークな質問の-1が適切であるかどうかはわかりませんが、私は逃げます。 Javadocはこう言っています。「割り込み可能なチャネルでこのスレッドがI/O操作でブロックされた場合、そのチャネルは閉じられます。これは私には当てはまりませんか?もし私が何をする必要があるのか​​分からないので、私は可能な解決策ではありません。 – Headline

+0

@Headline実際の見積もりには、[InterruptibleChannel](https://docs.oracle.com/javase/8/docs/api/java/nio/channels/InterruptibleChannel.html)というJavaクラスがあります。 BufferedReader *は例外をスローしているかもしれませんが、何もしていないので、あなたは知らないでしょう。 – matt

答えて

2

ここでの一般的なパターンは、ソケットからの1つのスレッド処理出力(待機中のブロッキング)を行い、メッセージを要求したものにディスパッチすることです。

複数のプロジェクトで好きな実装は、ジェネリックヘッダー(メッセージタイプも含む)の一部としてランダムに生成されたIDを「要求」に追加し、サーバーが常にIDをミラーリングするようにすることですその応答は、クライアントがどのタイプのメッセージであるかを気にせずに要求を応答に関連付けることを可能にする。

具体的には、のような2つのパブリック関数を持つクラス:sendRequest(type, body, callback)registerUnsolicitedHandler(type, callback)のようなものです。

sendRequestは、typeとランダムに生成されたIDを持つメッセージヘッダーを作成し、コールバック関数への参照と共に保留中の応答のリストに追加して、完了したメッセージをサーバーに送信します。

registerUnsolicitedHandler名前が示すとおり、受信メッセージにIDがない場合に使用されるメッセージタイプのマップにコールバック関数が追加されます。

着信メッセージを処理する別のスレッドでは、受信したデータをデシリアライズして、ヘッダーからタイプとIDを取得します。メッセージにIDがあれば、保留中の応答リストを検索し、メインスレッドでは、ロックのような細かいところを見ています)、そうでない場合は、指定された型の迷惑なハンドラリストを検索し、そのコールバックを呼び出します。

関連する問題