Seneca
Seneca

Reputation: 2412

Minimal socket http server

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

Answers (1)

Jonathan Gilbert
Jonathan Gilbert

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

Related Questions