Reputation: 287
I am now writing a http server and I am having problem with reading from a socket.
My problem is that the inputStream
from the client never ends and it keeps reading until the client is closed.
I know that the client doesn't close the connection with the server immediately after sending the http request.
How can I quit the while loop
when client has sent all the request data (i.e. headers + body).
while (in.hasNextLine()) {
String line = in.nextLine();
if (line.equals("")){ // last line of request header is blank
break; // quit while loop when last line of header is reached
} else {
request = request + line + "\n";
}
}
After reading comments and answer from you guys, this is what I came up with,
is = incoming.getInputStream();
os = incoming.getOutputStream();
in = new Scanner(is);
out = new DataOutputStream(os);
RequestHandler rh = new RequestHandler();
int length = 0;
while (in.hasNextLine()) {
String line = in.nextLine();
if (line.equals("")) { // last line of request message
// header is a
// blank line
break; // quit while loop when last line of header is
// reached
}
if (line.startsWith("Content-Length: ")) { // get the
// content-length
int index = line.indexOf(':') + 1;
String len = line.substring(index).trim();
length = Integer.parseInt(len);
}
request = request + line + "\n";
}
byte[] body = new byte[length];
int i = 0;
while (i < length) {
byte b = in.nextByte();
body[i] = b;
i++;
}
but, I still don't get it about reading by bytes. I can write my code to read until -1, but still stuck when there is no EOF and client is not closing connection.
Upvotes: 3
Views: 11573
Reputation: 1
I want to share my code that works great:
private static String getClientRequest(Socket client) throws IOException, SocketException {
System.out.println("Debug: got new client " + client.toString());
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8"));
StringBuilder requestBuilder = new StringBuilder();
String line;
int contectLegnth = 0;
while (!(line = br.readLine()).isBlank()) {
requestBuilder.append(line + "\r\n");
if (line.toLowerCase().startsWith("content-length")) {
contectLegnth = Integer.parseInt(line.split(":")[1].trim());
}
}
StringBuilder requestBodyBuilder = new StringBuilder();
if (contectLegnth > 0) {
int read;
while ((read = br.read()) != -1) {
requestBodyBuilder.append((char) read);
if (requestBodyBuilder.length() == contectLegnth)
break;
}
requestBuilder.append("\r\n" + requestBodyBuilder);
}
return requestBuilder.toString();
}
Upvotes: 0
Reputation: 287
I've got it :) Thank you guys for comments and answers...
is = incoming.getInputStream(); // initiating inputStream
os = incoming.getOutputStream(); // initiating outputStream
in = new BufferedReader(new InputStreamReader(is)); // initiating
// bufferReader
out = new DataOutputStream(os); // initiating DataOutputSteream
RequestHandler rh = new RequestHandler(); // create a
// requestHandler
// object
String line;
while ((line = in.readLine()) != null) {
if (line.equals("")) { // last line of request message
// header is a
// blank line (\r\n\r\n)
break; // quit while loop when last line of header is
// reached
}
// checking line if it has information about Content-Length
// weather it has message body or not
if (line.startsWith("Content-Length: ")) { // get the
// content-length
int index = line.indexOf(':') + 1;
String len = line.substring(index).trim();
length = Integer.parseInt(len);
}
request.append(line + "\n"); // append the request
} // end of while to read headers
// if there is Message body, go in to this loop
if (length > 0) {
int read;
while ((read = in.read()) != -1) {
body.append((char) read);
if (body.length() == length)
break;
}
}
request.append(body); // adding the body to request
Upvotes: 4
Reputation: 12148
There are 3 ways of detecting the end of the stream depending on what requests you are handling:
GET
or HEAD
request, you only need to read the HTTP headers, request body is normally ignored if it exists, so when you encounter \r\n\r\n
, you reach the end of the request(actually the request headers).POST
method, read the Content-Length
in the header and read up to Content-Length
bytes.POST
method and the Content-Length
header is absent, which is most likely to happen, read until -1
is returned, which is the signal of EOF
.Upvotes: 6