Reputation: 2412
I'm trying to make a very simple http server with the low-level Unix module to get a better understanding of how a http server actually works. This is my current code:
let () =
let socket_fd = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
let _ = Unix.bind socket_fd (Unix.ADDR_INET ((Unix.inet_addr_of_string "127.0.0.1"), 8888)) in
let _ = Unix.listen socket_fd 1 in
let (file_descr,sockaddr) = Unix.accept socket_fd in
let b = Bytes.create 1024 in
let _ = Unix.recv file_descr b 0 0 [Unix.MSG_PEEK] in
print_endline b;
When I open a webbrowser & surf to localhost:8888
the program displays a
newline and exits. Why isn't it printing out the request?
According to the Unix
module documentation recv
has the following signature:
val recv : file_descr -> bytes -> int -> int -> msg_flag list -> int
Receive data from a connected socket.
What is the meaning of the ... -> int -> int -> ...
? I have no idea what I should be passing in those two ints.
Also how do I know beforehand what size a should give to bytes
?
Upvotes: 3
Views: 458
Reputation: 4425
Part of the answer lies in the C mapping of recv (sendrecv: .opam/version/build/ocaml/otherlibs/unix/sendrecv.c ).
CAMLprim value unix_recv(value sock, value buff, value ofs, value len,
value flags)
{
int ret, cv_flags;
long numbytes;
char iobuf[UNIX_BUFFER_SIZE];
cv_flags = convert_flag_list(flags, msg_flag_table);
Begin_root (buff);
numbytes = Long_val(len);
if (numbytes > UNIX_BUFFER_SIZE) numbytes = UNIX_BUFFER_SIZE;
enter_blocking_section();
ret = recv(Int_val(sock), iobuf, (int) numbytes, cv_flags);
leave_blocking_section();
if (ret == -1) uerror("recv", Nothing);
memmove (&Byte(buff, Long_val(ofs)), iobuf, ret);
End_roots();
return Val_int(ret);
}
So first int
is an offset within the buffer, and second int
is the length of the retrieval - that you shoud not set to 0.
Happy new year anyway ;)
Upvotes: 3