To learn Erlang I am trying to implement a tiny web server based on gen_tcp
. Unfortunately, my code seems to trigger some wired behaviour. To demonstrate the problem I have attached a minimised version of my implementation which is sufficient to reproduce the problem. It is just delivering a static 200 OK, no matter what the HTTP request was.
The problem arises when I try to run ab
(Apache HTTP server benchmarking) against my web server (using loopback interface). Without any concurrent requests (-c
) everything is running just fine. However, if I use -c 8
or -c 16
, the call to gen_tcp:accept/1
seems to fail on some sockets as I see a number of request: closed
lines in the shell.
What makes the whole story even weirder is, that I see different behaviours on different operating systems:
- OS X+Erlang/OTP 18:
ab
reports "Connection reset by peer" almost immediately after starting. - Debian+Erlang R15B01: All but two of the HTTP requests seem to run through. But then,
ab
hangs for a few seconds and reports "The timeout specified has expired, Total of 4998 requests completed", when i runab
with-n 5000
. Similarly, 14998 is reported when I run 15000 tests.
This one does not seem to be the problem. I am honestly quite lost and therefore appreciate any help! :) Thanks!
server(Port) ->
Opt = [list, {active, false}, {reuseaddr, true}],
case gen_tcp:listen(Port, Opt) of
{ok, Listen} ->
handler(Listen),
gen_tcp:close(Listen),
ok;
{error, Error} ->
io:format("init: ~w~n", [Error])
end.
handler(Listen) ->
case gen_tcp:accept(Listen) of
{ok, Client} ->
request(Client),
handler(Listen);
{error, Error} ->
io:format("request: ~w~n", [Error])
end.
request(Client) ->
Recv = gen_tcp:recv(Client, 0),
case Recv of
{ok, _} ->
Response = reply(),
gen_tcp:send(Client, Response);
{error, Error} ->
io:format("request: ~w~n", [Error])
end,
gen_tcp:close(Client).
reply() ->
"HTTP/1.0 200 OK\r\n" ++
"Content-Length: 7\r\n\r\n"
"static\n".