2017-05-11 10 views
0

私はソケットプログラミングが初めてです。チュートリアルからクライアントが文字列をサーバーに送信し、サーバーが文字列を大文字に変換してクライアントに返すJavaサーバークライアントコードをコピーしました。ソケットプログラミングでreadLine()にコードが詰まっています

大文字にする文字列を入力するJTextFieldと、大文字の文字列の出力を示すJTextAreaがあります。

しかし、問題は私がJTextFieldに入力を与えて、コードを入力するとハングすることです。デバッグでは、クライアントがreadLine()でサーバーから送信された大文字の文字列を読み取ろうとしたときにコードがハングすることが判明しました。

私はそれを取り除く方法を知りません。 Stack Overflowでいくつか似たような質問を読んだが解決策を試したが、望みはなかった。

Serverコード:

public class CapitalizeServer { 

/** 
* @param args the command line arguments 
* @throws java.io.IOException 
*/ 
public static void main(String[] args) throws IOException { 
    System.out.println("The Capitalization Server is running"); 

    int clientNumber = 0; 
    try (ServerSocket listener = new ServerSocket(1234)) { 
     while(true) { 
      new Capitalizer(listener.accept(), clientNumber++).start(); 
     } 
    } 
} 

private static class Capitalizer extends Thread { 

    Socket socket; 
    int clientNumber; 

    public Capitalizer(Socket socket, int clientNumber) { 
     this.socket = socket; 
     this.clientNumber = clientNumber; 
     log("New connection with client# " + clientNumber + " at " + socket); 
    } 

    @Override 
    public void run() { 
     try { 

      // Decorate the streams so we can send characters 
      // and not just bytes. Ensure output is flushed 
      // after every newline. 
      BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
      PrintWriter out = new PrintWriter(socket.getOutputStream(), true); 

      // Send a welcome message to the client. 
      out.println("Hello, you are client # " + clientNumber + "."); 
      out.println("Enter a line with only a period to quit"); 

      // Get messages from the client, line by line; return them capitalized 
      while(true) { 
       String input = in.readLine(); 
       if(input == null || input.equals(".")) { 
        break; 
       } 

       //System.out.println("Coming input: " + input); 
       out.println(input.toUpperCase()); 
       //System.out.println("UpperCase: " + input.toUpperCase()); 
      } 

     } catch (IOException ex) { 
      log("Error handling client# " + clientNumber + ": " + ex); 

     } finally { 
      try { 
       socket.close(); 
      } catch (IOException ex) { 
       log("Could not close a socket. What's going on?"); 
      } 

      log("Connection with client# " + clientNumber + " closed"); 
     } 
    } 

    /** 
    * Logs a simple message. In this case we just write the 
    * message to the server applications standard output. 
    */ 
    private void log(String message) { 
     System.out.println(message); 
    } 
} 

}

クライアントコード:

public class CapitalizeClient { 

private BufferedReader in; 
private PrintWriter out; 
private JFrame frame = new JFrame("Capitalize Client"); 
private final JTextField dataField = new JTextField(40); 
private final JTextArea messageArea = new JTextArea(8,60);  
/** 
* Constructs the client by laying out the GUI and registering a 
* listener with the textField so that pressing Enter in the 
* listener sends the textField contents to the server. 
*/ 
public CapitalizeClient() { 

    // Layout GUI 
    messageArea.setEditable(false); 
    frame.getContentPane().add(dataField, "North"); 
    frame.getContentPane().add(new JScrollPane(messageArea), "Center"); 

    // Add Listeners 
    dataField.addActionListener(new ActionListener() { 

     /** 
     * Responds to pressing the enter key in the textField 
     * by sending the contents of the text field to the 
     * server and displaying the response from the server 
     * in the text area. If the response is "." we exit 
     * the whole application, which closes all sockets, 
     * streams and windows. 
     */ 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      out.println(dataField.getText()); 
      String response; 

      try { 
    // ******* The code stucks here ************* 
       response = in.readLine(); 

       if(response == null) { 
        System.exit(0); 
       } 
      } catch (IOException ex) { 
       response = "Error: " + ex; 
      } 
      messageArea.append(response + "\n"); 
      dataField.selectAll(); 
     } 
    }); 
} 

public void connectToServer() throws IOException { 

    // Get the server address from a dialog box. 
    String serverAddress = JOptionPane.showInputDialog(frame, "Enter IP Address of the Server:" , 
     "Welcome to the Capitalization Program", JOptionPane.QUESTION_MESSAGE); 

    // Make connection and initialize streams 
    Socket socket = new Socket(serverAddress, 1234); 
    in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
    out = new PrintWriter(socket.getOutputStream(), true); 

    // Consume the initial welcoming messages from the server 
    for(int i=0; i < 3; i++) { 
     messageArea.append(in.readLine() + "\n"); 
    } 
} 

public static void main(String[]args) throws IOException { 
    CapitalizeClient client = new CapitalizeClient(); 
    client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    client.frame.pack(); 
    client.frame.setVisible(true); 
    client.connectToServer(); 
} 

}

+0

あなたのコードには、「すべての改行後に出力がフラッシュされるようにする」というコメントがあります。私にとって、あなたは出力を洗い流すようには見えません。 – Davatar

+0

PrintWriterのコンストラクタでautoflushをtrueに設定しました。 println()に遭遇すると、出力はフラッシュされます。しかし、出力を手動でフラッシュするout.flush()も追加しました。変更は発生しませんでした。 :( –

答えて

4

あなたの問題は、クライアント側にあります。あなたのウェルカムメッセージが二行ない3であるとしてあなたは、二回しかループを反復処理する必要がある方法

public void connectToServer() throws IOException { 

    // Get the server address from a dialog box. 
    String serverAddress = JOptionPane.showInputDialog(frame, "Enter IP Address of the Server:", 
      "Welcome to the Capitalization Program", JOptionPane.QUESTION_MESSAGE); 

    // Make connection and initialize streams 
    Socket socket = new Socket(serverAddress, 1234); 
    in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
    out = new PrintWriter(socket.getOutputStream(), true); 

    // Consume the initial welcoming messages from the server 
    for (int i = 0; i < 2; i++) { 
     messageArea.append(in.readLine() + "\n"); 
    } 
} 

のコードを置き換えます。

常に通信は同期している必要があります。サーバーから2行を送信する場合は、何かを送信する前にクライアント上で2行を読み取る必要があります。

+0

ありがとうございました!!!!それは実現しました!!! :) :) –

+0

あなたは歓迎です – kism3t

関連する問題