简体   繁体   English

套接字编程中的代码卡在readLine()中

[英]Code stucks in readLine() in socket programming

I am new to socket programming. 我是套接字编程的新手。 I copied a java server client code from a tutorial where the client sends a string to the server and the server capitalizes the string and sends it back to the client. 我从教程中复制了Java服务器客户端代码,在该教程中,客户端将字符串发送到服务器,服务器将字符串大写并将其发送回客户端。

I have a JTextField where I input the string to be capitalized and a JTextArea where the capitalized string output is shown. 我有一个JTextField,其中输入了要大写的字符串,还有一个JTextArea,其中显示了大写的字符串输出。

But the problem is when I give input in the JTextField and press enter the code hangs. 但是问题是当我在JTextField中输入内容并按Enter时,代码挂起。 By debuging I have found that the code is hang when client tries to read the capitalized string sent by server with readLine(). 通过调试,我发现当客户端尝试使用readLine()读取服务器发送的大写字符串时,代码已挂起。

I do not know how to get rid of it. 我不知道如何摆脱它。 I have read several similar questions in Stack Overflow and tried the solutions but no hope. 我已经在Stack Overflow中阅读了几个类似的问题,并尝试了解决方案,但没有希望。

Server code: 服务器代码:

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);
    }
}

} }

Client code: 客户代码:

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();
}

} }

your problem is on client side. 您的问题是在客户端。 Replace the code of method 替换方法代码

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");
    }
}

You need to iterate through the loop only twice, as your welcome message is two lines not three. 您只需要遍历循环两次,因为欢迎消息是两行而不是三行。

The communication always needs to be synchronous. 通信始终需要同步。 If you send two lines from server you need to read two lines on client before you send something. 如果从服务器发送两行,则在发送内容之前,需要在客户端上阅读两行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM