Reputation: 2412
I'm getting my feet wet with unix system programming, and am currently trying to implement a minimal http server with sockets.
Currently I have the following code (it's ocaml, the flow is the same as in any language)
let establish_server () =
let socket = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
Unix.bind socket (Unix.ADDR_INET ((Unix.inet_addr_of_string "127.0.0.1"), 8888));
Unix.listen socket 128;
print_endline "accepting now";
while true do
let (service_socket, addr) = Unix.accept socket in
print_endline "Something arrived!";
let b = Bytes.create 1024 in
let _ = Unix.recv service_socket b 0 1024 [Unix.MSG_PEEK] in
print_endline @@ Bytes.to_string b;
let response = Bytes.of_string "HTTP/1.1 200 OK\n\nHey from Ocaml!" in
let _ = Unix.send service_socket response 0 (Bytes.length response) [Unix.MSG_PEEK] in
Unix.close service_socket;
done
Why do I have to close the socket to receive something in the browser when I visit 127.0.0.1:8888? If I don't close the socket on the last line, my browser keeps on spinning forever. Can't you just send something to the other end of the socket? Why doesn't the browser show anything, if I don't close the socket?
Upvotes: 0
Views: 180
Reputation: 3860
There are (at least) three big things you need to do to be handling HTTP/1.1 properly:
1) You need to buffer input, because the browser's request might not arrive in a single packet. This means that the Unix.recv
call may receive a partial request, and the next call will retrieve the rest of the request (or the next chunk). The simplest approach is to wrap the stream in some sort of reader that lets you request an entire line synchronously.
2) When sending a response, you have to supply a Content-Length
header. Without this, the browser doesn't know when the data is finished -- and without it, the browser can't tell the difference between the response being completed and the connection being unexpected closed.
3) In HTTP 1.1, connections are assumed to be persistent unless the server explicitly tells the client that they aren't. Your server will perform better if you support Connection: keep-alive
, but for a minimalist implementation, you should at least send a Connection: close
response header.
Upvotes: 1