Erlang TCP 套接字关闭
Erlang TCP sockets get closed
为了学习 Erlang,我正在尝试实现一个基于 gen_tcp
的微型 Web 服务器。不幸的是,我的代码似乎触发了一些有线行为。为了演示该问题,我附上了我的实现的最小化版本,它足以重现该问题。它只是提供一个静态的 200 OK,不管 HTTP 请求是什么。
当我尝试 运行 ab
(Apache HTTP 服务器基准测试)针对我的 Web 服务器(使用环回接口)时出现问题。没有任何并发请求 (-c
) 一切都 运行ning 就好了。但是,如果我使用 -c 8
或 -c 16
,对 gen_tcp:accept/1
的调用似乎在某些套接字上失败,因为我在 shell 中看到许多 request: closed
行.
让整个故事更奇怪的是,我在不同的操作系统上看到了不同的行为:
- OS X+Erlang/OTP 18:
ab
几乎在开始后立即报告 "Connection reset by peer"。
- Debian+Erlang R15B01:除两个 HTTP 请求外,其他所有请求似乎都 运行 通过。但是,
ab
挂起几秒钟并报告 "The timeout specified has expired, Total of 4998 requests completed",当我 运行 ab
和 -n 5000
时。同样,当我运行 15000次测试时报告14998。
This one 好像不是问题。老实说,我很迷茫,因此感谢您的帮助! :) 谢谢!
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".
当您增加使用 ab -c N
发送的并发请求数时,它会立即打开到服务器的多个 TCP 套接字。
默认情况下,使用 gen_tcp:listen/2 打开的套接字将仅支持五个未完成的连接请求。使用 {backlog, N} 选项将未完成的连接请求数增加到 gen_tcp:listen/2.
我在 OS X 上用 ab 测试了你的代码,发现这解决了 "Connection reset by peer" 的问题。
为了学习 Erlang,我正在尝试实现一个基于 gen_tcp
的微型 Web 服务器。不幸的是,我的代码似乎触发了一些有线行为。为了演示该问题,我附上了我的实现的最小化版本,它足以重现该问题。它只是提供一个静态的 200 OK,不管 HTTP 请求是什么。
当我尝试 运行 ab
(Apache HTTP 服务器基准测试)针对我的 Web 服务器(使用环回接口)时出现问题。没有任何并发请求 (-c
) 一切都 运行ning 就好了。但是,如果我使用 -c 8
或 -c 16
,对 gen_tcp:accept/1
的调用似乎在某些套接字上失败,因为我在 shell 中看到许多 request: closed
行.
让整个故事更奇怪的是,我在不同的操作系统上看到了不同的行为:
- OS X+Erlang/OTP 18:
ab
几乎在开始后立即报告 "Connection reset by peer"。 - Debian+Erlang R15B01:除两个 HTTP 请求外,其他所有请求似乎都 运行 通过。但是,
ab
挂起几秒钟并报告 "The timeout specified has expired, Total of 4998 requests completed",当我 运行ab
和-n 5000
时。同样,当我运行 15000次测试时报告14998。
This one 好像不是问题。老实说,我很迷茫,因此感谢您的帮助! :) 谢谢!
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".
当您增加使用 ab -c N
发送的并发请求数时,它会立即打开到服务器的多个 TCP 套接字。
默认情况下,使用 gen_tcp:listen/2 打开的套接字将仅支持五个未完成的连接请求。使用 {backlog, N} 选项将未完成的连接请求数增加到 gen_tcp:listen/2.
我在 OS X 上用 ab 测试了你的代码,发现这解决了 "Connection reset by peer" 的问题。