2016-05-26 3 views
0

ソケットによるスレッドの読み書きに問題があります。サーバーはerlangにあり、クライアントはJavaにあります。Javaエラーソケット通信

PrintWriter printer = new PrintWriter(socket.getOutputStream(), true); 
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 
TransmitterTwo trans = new TransmitterTwo(socket); 
trans.start(); // Gets the message from socket 

TransmitterTwoクラス::私はそれをやっている方法はこれです

public class TransmitterTwo extends Thread { 
Socket socket; 
String message; 

TransmitterTwo(Socket socket) { 
    this.socket = socket; 
} 

public String getMessageFromSocket() { 
    return message; 
} 

public void run() { 
    try { 
    String response = null; 
    BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
    while ((response = reader.readLine()) != null) { 
    System.out.println("Server response: "+ response); 
    this.message = response; 
    } 

    socket.close(); 
} catch(IOException e) { 
    e.printStackTrace(); 
} 
} 
} 

問題は、メインクライアントクラスです。アイデアは、コンソールからの入力を受け取り、ソケットに送信し、サーバーはロジックを処理し、ソケットを介して応答を送信することです。その後、このクライアントで私は応答をチェックし、何をする必要があるかを行います。それは私が...私がログインした後、私は「register_ok」を受信、登録、登録の流れだなどなど、私はトラブルを抱えているループの一部はこれです:

while(true) { 
    String readerInput = reader.readLine(); // Read from console 
    printer.println(readerInput.trim()); // Sends it to the socket 

    while(trans.message == null); 
    socketMessage = trans.message; 

が、これは正しいアプローチですか?問題は 'socketmessage'が前に受信したメッセージを出力することです。それはlike..1のステップの後ろにあります。これは明らかにスレッド関連ですが、問題を理解できません。ありがとう

答えて

1

あなたの主なスレッドが更新される変数を待つことを浪費しているので、現在のアプローチは最適ではありません。 Javaでメモリの可視性がどのように機能するかによって、実際には更新されることはないように見えるかもしれません。あるいは、その変数にアクセスするときに古い値が得られるかもしれません。より堅牢なアプローチは、Javaでのコレクションに建てられたのいくつかを使用して、スレッド間でメッセージを渡すために、次のようになります。

public static void main(String[] args) { 
    // This queue will be the link between the threads where 
    // they can pass messages to each other 
    BlockingQueue<String> messages = new LinkedBlockingQueue<>(); 

    PrintWriter printer = new PrintWriter(socket.getOutputStream(), true); 
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 
    TransmitterTwo trans = new TransmitterTwo(socket, queue); 
    trans.start(); // Gets the message from socket 

    ... 

    while(true) { 
      String readerInput = reader.readLine(); // Read from console 
      printer.println(readerInput.trim()); // Sends it to the socket 

      // Wait for the other thread to push a message in to the queue. 
      String recv = messages.take(); 
    } 
} 

public class TransmitterTwo extends Thread { 
    final Socket socket; 
    final BlockingQueue<String> queue; 

    TransmitterTwo(Socket socket, BlockingQueue<String> queue) { 
     this.socket = socket; 
     this.queue = queue; 
    } 

    public void run() { 
     try { 
      String response = null; 
      BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
      while ((response = reader.readLine()) != null) { 
       System.out.println("Server response: " + response); 
       // Add the response from the server to the queue 
       queue.add(response); 
      } 

      socket.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

このアプローチは、古い値を取得することはありませんし、メインスレッド上のテイク()操作がされるまでブロックします。サーバーから何らかの応答があります。

+0

うわー、それは私が予想していたよりも良い答えでした。私の専門的な未来はこの笑に依存しているので、私は絶望的です。だから、あなたのアプローチでは、N人のクライアントを持ち、メッセージを正しく得ることができると思いますか?私はスレッド間で値を渡したくないので、私は各クライアントがソケットと話をし、独立したトランスミッタ/レシーバを持っていなければなりません。それはサービスのようなもので、各クライアントはソケットから話を聞くことができます...。それにもかかわらず、私はこのアプローチを試して、答えます。ありがとう、たくさんの男、本当に感謝しています。 –

+0

それは働いた!どうもありがとう! –

+0

ちょっとしたエラーです。ソケットに送信された文字列は、最後には常に "\ n"を持ちますが、trim()メソッドを使用しても、\ nが送信されます。なぜか分かりますか? –

関連する問題