简体   繁体   English

从套接字读取直到在Java中\\ r \\ n

[英]Read from socket until \r\n in Java

I want to implement a POP3 client. 我想实现一个POP3客户端。 I know that in POP3 protocol, each message ends with \\r\\n . 我知道在POP3协议中,每个消息都以\\r\\n结尾。 I want to write a recvuntil method in Java, which will be able to receive a whole message at once. 我想用Java编写recvuntil方法,该方法将能够立即接收整个消息。

It super easy in Python: 在Python中超级简单:

def recv_all_until_ver3(s, crlf):
    data = ""
    while data[-len(crlf):] != crlf:
        data += s.recv(1)
    return data

However, when I tried to do the same in Java: 但是,当我尝试在Java中执行相同操作时:

class JavaApplication1 {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws IOException {
        // TODO code application logic here
        String serverAddress = "interia.pl";
        int port = 110;

        Socket s = new Socket(serverAddress, port);
        BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
        String answer = "";
        while (!answer.contains("\r\n")) {
            answer = input.readLine();
            System.out.println(answer);
        }
    }
}

It receives one message and hands instead of end itself. 它收到一条消息并举手而不是结束。 Is there any way to implement this method in Java? 有什么方法可以用Java实现此方法吗? Can I just read characters one by one, instead of whole line until I find \\r\\n in my message? 在消息中找到\\r\\n之前,我可以只逐个而不是整行地读取字符吗? Thank you. 谢谢。

The Python code reads one octet at a time, immediately appends it to answer and signals it's done if at the current iteration answer ends with CRLF . Python代码一次读取一个八位位组,立即将其附加到answer ,如果当前迭代的answerCRLF结尾,则表明已完成。

The Java code hangs because BufferedReader.readLine() returns the line content after stripping the line termination. Java代码挂起,因为BufferedReader.readLine()在剥离行终止后返回行内容。 At this point answer does not contain CRLF , so readLine() is called once again, and since the stream is not closed from the other end (your program would then throw a NullPointerException ) and you have an infinite read timeout (you would see a SocketTimeoutException ), it hangs, forever waiting for the next line. 此时answer不包含CRLF ,因此再次调用readLine() ,并且由于没有从另一端关闭流(您的程序随后将抛出NullPointerException ),并且您有无限的读取超时(您将看到一个SocketTimeoutException ),它会挂起,永远等待下一行。

The correct version is 正确的版本是

Socket socket = connect(); // Implement this
Scanner scanner = new Scanner(new InputStreamReader(socket.getInputStream(), "ASCII"));
scanner.useDelimiter("\r\n");
String response = scanner.nextLine();
socket.close();

Notes: 笔记:

  • always set a timeout on sockets. 总是在套接字上设置超时。
  • you may want to account for multiline messages . 您可能需要考虑多行消息

you can use the Scanner class (it accepts an InputStream as a constructor param ) and set the delimiter using useDelimiter method. 您可以使用Scanner类(它接受InputStream作为构造函数param)并使用useDelimiter方法设置定界符。 to read messages that end with \\r\\n 阅读以\\r\\n结尾的消息

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

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