mirx
mirx

Reputation: 626

Read from socket until \r\n in Java

I want to implement a POP3 client. I know that in POP3 protocol, each message ends with \r\n. I want to write a recvuntil method in Java, which will be able to receive a whole message at once.

It super easy in 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:

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? Can I just read characters one by one, instead of whole line until I find \r\n in my message? Thank you.

Upvotes: 0

Views: 2106

Answers (2)

Raffaele
Raffaele

Reputation: 20885

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.

The Java code hangs because BufferedReader.readLine() returns the line content after stripping the line termination. 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.

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:

Upvotes: 1

Sheinbergon
Sheinbergon

Reputation: 3063

you can use the Scanner class (it accepts an InputStream as a constructor param ) and set the delimiter using useDelimiter method. to read messages that end with \r\n

Upvotes: 0

Related Questions