0

I'm trying to write a httpserver using sockets and I meet this problem. As everyone knows , a Http request is like this.

GET /index.html HTTP/1.1
Cache-Control: max-age=0
Host: 127.0.0.1
Accept:xxxxx
User-Agent: xxxx
Connection: keep-alive
CRLF
This is message body!

The question is how can I get full Http request including message body. I tried to write like this.

ServerSocket serverSocket = new ServerSocket(8000);
while (true) {
 Socket socket = serverSocket.accept();
 new Thread() {
  {
   InputStream is = socket.getInputStream();
   BufferedReader input = new BufferedReader(new InputStreamReader(is));
   String line = null;
   while ((line = input.readLine()) != null) {
    System.out.println(line);
   }
   System.out.print("finish");
  }
 }.start();
}

And the console would never print "finish".Then I changed like this

ServerSocket serverSocket = new ServerSocket(8000);
while (true) {
 Socket socket = serverSocket.accept();
 new Thread() {
  {
   InputStream is = socket.getInputStream();
   BufferedReader input = new BufferedReader(new InputStreamReader(is));
   String line = null;
   while (input.ready()) {
    line = input.readLine();
    System.out.println(line);
   }
   System.out.println("finish");
  }
 }.start();
}

Things go to be better, We can see "finish"! But if I refresh the page a little bit faster.The bufferdreader will not be ready and don't get in the while{} !

I want to print all the rerquest and "finish"

Please help me. Thanks a lot!!

Malt
  • 25,324
  • 9
  • 56
  • 86
lxhsb
  • 13
  • 2
  • The stream will end only when the client closes the connection. Since the request is to keep the connection alive, it doesn't do that, as it will want to send the next request on the same connection. You should write your loop based on the length header (and remember that most GET requests do not send a request body!) – RealSkeptic Feb 14 '17 at 08:55
  • 'httpserver throw socket' is meaningless. Unclear what you're asking. – user207421 Feb 14 '17 at 09:06
  • @EJP he meant "through" – Malt Feb 14 '17 at 09:08
  • @Maltn Maybe so, maybe not. It's up to him to clarify. Guesswork is just a waste of time. – user207421 Feb 14 '17 at 09:08
  • Sorry and thx for everyone ! – lxhsb Feb 14 '17 at 09:17

1 Answers1

0

Both your approaches are incorrect.

In the first one, input.readLine() will return null only when the end of the stream has been reached, not when the request ended. That means that you'll loop there as long as the browser maintains the TCP connection open. That might take a while. Plus, multiple requests might be sent on the same connection, so you might end up printing all of them (I don't know if that's what you want to do).

In the second one, you have timing problem. input.ready() checks whether the receive buffer has any content to read, instead of checking whether the request ended. So you might end up printing only a part of the request instead of waiting for the whole thing. With this approach and the right timings, you might end up printing a part of a request, multiple requests, or anything in between (like a request and a half).

Also note that HTTP GET messages almost never carry any payalod, and no browser will requests like the one in your example.

Malt
  • 25,324
  • 9
  • 56
  • 86
  • @lxhsb You need a seriously good knowledge of RFC 2616 and friends to implement HTTP, specifically the parts about content length and transfer-encoding. Guesswork is not sufficient. – user207421 Feb 14 '17 at 09:09
  • Read until the CR LF CR LF. That'll give you the header. If you need the payload, you'd need to parse the header and figure out how much payload there is. – Malt Feb 14 '17 at 09:10
  • @Malt So if a request have message body ,it will have "content-length" like a response ?Is that correct ? – lxhsb Feb 14 '17 at 09:14
  • 1
    Either that, or the request can be [chunked](https://en.wikipedia.org/wiki/Chunked_transfer_encoding). As EJP suggested, you should read about the protocol you're trying to implement... – Malt Feb 14 '17 at 09:20