Java网络和#x27;readLine()';在客户端的多行响应上

Java网络和#x27;readLine()';在客户端的多行响应上,java,networking,Java,Networking,我目前正在编写一个邮件客户端,它只需打开与邮件服务器的连接并从中接收响应 但是,当我从服务器收到响应时,它仅在响应为一行时工作。当响应不止一行(多行)时,它只接收第一行响应 如果我可以知道响应的格式,例如每行末尾有\n,则设置响应的格式会更容易。但由于我只编写客户端而不是服务器,所以我也不知道响应格式 下面是我写的代码 public class Main { private static Socket client; private static final BufferedReader br

我目前正在编写一个邮件客户端,它只需打开与邮件服务器的连接并从中接收响应

但是,当我从服务器收到响应时,它仅在响应为一行时工作。当响应不止一行(多行)时,它只接收第一行响应

如果我可以知道响应的格式,例如每行末尾有\n,则设置响应的格式会更容易。但由于我只编写客户端而不是服务器,所以我也不知道响应格式

下面是我写的代码

public class Main {
private static Socket client;
private static final BufferedReader br
        = new BufferedReader(new InputStreamReader(System.in));

public static void main(String[] args) {
    try {
        /* Input format checking before opening a connection,
            the input must be a form of mail_server and port_number */
        if (args.length != 2)
            System.exit(1);

        /* Set up the connection to mail server from the command line */
        client = new Socket(args[0], Integer.parseInt(args[1]));

        /* Initialize sender that sends message to the server */
        PrintStream sender = new PrintStream(client.getOutputStream());

        /* Initialize receiver that receives message from the server */
        BufferedReader receiver
                = new BufferedReader(
                        new InputStreamReader(client.getInputStream()));

        while (true) {
            /* Flushing buffer */
            String message;

            /* Printing the resulting response from the server */
            while ((message = receiver.readLine()) != null) {
                System.out.println(message);
            }

            /* Get input message from the user */
            message = br.readLine();

            /* If the user inputs "exit", then the program terminates */
            if (message.equals("exit")) System.exit(1);

            /* If not exit, send the message to server */
            sender.println(message);
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            client.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
}

我也试过,

// Assuming that the output format has '\n' at the end of each lines
String[] messages = receiver.readLine().split("\n");
但它也只打印出响应的第一行

我在上看到了非常类似的问题,但问题已经通过编辑服务器代码得到了解决,我只能更改客户端代码

谁能给我一些建议吗


提前感谢。

从服务器读取的循环将继续读取,直到服务器通过关闭它发出流结束的信号。我猜服务器正在等待来自客户端的命令,客户端正在等待服务器关闭流。所以两者都被卡住了

您需要分析来自服务器的消息,以确定响应何时结束。例如,
LIST
命令生成如下响应:

+OK 2消息(320个八位字节)
1 120
2 200
.

响应由一个单周期的行终止。服务器还不会关闭流,否则它将无法响应未来的命令。

从服务器读取的循环将继续读取,直到服务器通过关闭流来发出流结束的信号。我猜服务器正在等待来自客户端的命令,客户端正在等待服务器关闭流。所以两者都被卡住了

您需要分析来自服务器的消息,以确定响应何时结束。例如,
LIST
命令生成如下响应:

+OK 2消息(320个八位字节)
1 120
2 200
.

响应由一个单周期的行终止。服务器还不会关闭流,否则它将无法响应未来的命令。

Hm我让它与netcat一起工作,例如:

nc -l -p 31337
启动netcat后,您可以键入一些输入,这些输入将在连接后发送到客户端

因此,对于netcat,它是有效的。我建议只为一个目的使用变量

        while(true){
        /* Flushing buffer */
        String SvMessage;
        while (!receiver.ready()){} //wait for buffer
        /* Printing the resulting response from the server */
        while (receiver.ready()){
            SvMessage = receiver.readLine();
            System.out.println(SvMessage);
        }

        /* Get input message from the user */
        String userMessage = "hello";

        /* If the user inputs "exit", then the program terminates */
        if (userMessage.equals("exit")) System.exit(1);

        /* If not exit, send the message to server */
        sender.print(userMessage + "\r\n");
        }
我做了一些改变: 1.)将条件更改为br.ready() 2.)使用PrintStream.print(消息+“\r\n)代替PrintStream.println 3.)不使用BufferedReader进行用户输入,只发送“命令”(或hello) 4.)在(!receiver.ready()){}等待缓冲区填充时添加

因此,客户端现在将始终使用新命令(或“hello”)回复服务器


希望这有助于

Hm我将其用于netcat,例如:

nc -l -p 31337
启动netcat后,您可以键入一些输入,这些输入将在连接后发送到客户端

所以netcat是可行的。我建议只为一个目的使用变量

        while(true){
        /* Flushing buffer */
        String SvMessage;
        while (!receiver.ready()){} //wait for buffer
        /* Printing the resulting response from the server */
        while (receiver.ready()){
            SvMessage = receiver.readLine();
            System.out.println(SvMessage);
        }

        /* Get input message from the user */
        String userMessage = "hello";

        /* If the user inputs "exit", then the program terminates */
        if (userMessage.equals("exit")) System.exit(1);

        /* If not exit, send the message to server */
        sender.print(userMessage + "\r\n");
        }
我做了一些改变: 1.)将条件更改为br.ready() 2.)使用PrintStream.print(消息+“\r\n)代替PrintStream.println 3.)不使用BufferedReader进行用户输入,只发送“命令”(或hello) 4.)在(!receiver.ready()){}等待缓冲区填充时添加

因此,客户端现在将始终使用新命令(或“hello”)回复服务器


希望这能有所帮助

我认为主循环类似于“在检索新邮件时”,因此对套接字的读写是在主循环内完成的。你也可以读写一次@jsh114是这样吗?@Lord_Pedantestein非常感谢,这段代码工作得非常完美。虽然我接受了您的第一个和第四个更改,但并不是全部。@jsh114 u欢迎您。当然,这取决于你如何处理。。关于第4点,我选择“\r\n”是因为它在Linux和Windows上工作得最好(到目前为止:p),有很多可能表示换行符,例如,它可能会导致奇怪的问题。啊,我差点忘了这一点:-祝福^^我认为主循环类似于“在检索新邮件时”,所以对套接字的读写是在主循环内完成的。你也可以读写一次@jsh114是这样吗?@Lord_Pedantestein非常感谢,这段代码工作得非常完美。虽然我接受了您的第一个和第四个更改,但并不是全部。@jsh114 u欢迎您。当然,这取决于你如何处理。。关于第4点,我选择“\r\n”是因为它在Linux和Windows上工作得最好(到目前为止:p),有很多可能表示换行符,例如,它可能会导致奇怪的问题。啊,我差点忘了这一点:-祝福^^从套接字读取的部分看起来不错(但是从用户读取输入的代码只读取一行)。您确定服务器正在发送多条线路吗?如果您有服务器的代码,发布它会很有帮助。@tom我正在使用一家公司的邮件服务器,因此无法访问服务器代码。我确信服务器正在为特定的用户输入发送多行数据(因为我用C++完成了相同的任务),例如“LIST”和“RETR”,其中#是任意整数。此外,用户输入不能超过一行,因为它只包含简单的pop3命令。外部
while(true)
循环没有意义。一旦您从
readLine()
中获得空值,就是这样:将不再有任何数据。这段代码将在流的末尾无意识地旋转。移除外部循环。从套接字读取的部分看起来不错(但是从用户读取输入的代码只读取一行)。您确定服务器正在发送多条线路吗?如果您有服务器的代码,发布它会很有帮助。@tom我正在使用一家公司的邮件服务器,所以我可以