我构建了一个非常简单的并行 ssl 接受器。
-module(multiserver).
-export([start/0,client/1]).
%% This is a dummy SSL Erlang server/client example
start() ->
spawn_link(fun() -> init([]) end).
init([]) ->
ssl:start(),
{ok, ListenSocket} = ssl:listen(9990, [{certfile, "cert.pem"}, {keyfile, "privkey.pem"} ,{reuseaddr, true},{active, true}, binary]),
Pid = self(),
spawn_link(fun() -> listener(ListenSocket, Pid, 1) end),
spawn_link(fun() -> listener(ListenSocket, Pid, 2) end),
loop().
loop() ->
receive
{new, _Pid} ->
%% Do stuff here
loop()
end.
listener(ListenSocket, Pid, Num) ->
{ok, ClientSocket} = ssl:transport_accept(ListenSocket),
ok = ssl:ssl_accept(ClientSocket),
io:format("listener ~p accepted ~n", [Num]),
ok = ssl:send(ClientSocket, "server"),
io:format("listener ~p sent~n", [Num]),
receive
X -> io:format("listener ~p: ~p ~n", [Num, X])
after 5000 ->
io:format("listener ~p timeout ~n", [Num]),
timeout
end,
ssl:close(ClientSocket),
listener(ListenSocket, Pid, Num).
client(Message) ->
ssl:start(),
{ok, Socket} = ssl:connect("localhost", 9990, [binary, {active,true}], infinity),
receive
X -> io:format("~p ~n", [X])
after 2000 ->
timeout
end,
ok = ssl:send(Socket, Message),
ssl:close(Socket),
io:format("client closed~n").
我遇到的问题是监听器2似乎无法接收任何消息。该程序的示例运行如下所示:
首先,我在 shell 1 中启动服务器。 外壳1:
1> multiserver:start().
<0.34.0>
然后我从不同的 shell 调用 client/1 三次。 外壳2:
2> multiserver:client("client").
{ssl,{sslsocket,new_ssl,<0.51.0>},<<"server">>}
client closed
ok
3> multiserver:client("client").
{ssl,{sslsocket,new_ssl,<0.54.0>},<<"server">>}
client closed
ok
4> multiserver:client("client").
{ssl,{sslsocket,new_ssl,<0.56.0>},<<"server">>}
client closed
ok
这是服务器 shell 的打印输出。 外壳1:
listener 1 accepted
listener 1 sent
listener 1: {ssl,{sslsocket,new_ssl,<0.51.0>},<<"client">>}
listener 2 accepted
listener 2 sent
listener 1 accepted
listener 1 sent
listener 1: {ssl,{sslsocket,new_ssl,<0.54.0>},<<"client">>}
listener 2 timedout
2>
我花了几个小时来处理这个问题,但我不明白为什么监听器 2 无法接收任何数据。如果我编辑代码以使用 gen_tcp ,它会按预期工作。 我有什么遗漏的吗? 使用当前的 ssl 模块可以做到这一点吗?
最佳答案
超时的原因是在第二个进程中使用了套接字选项{active,false},即接收永远不会收到任何消息。
erlang docs for the ssl module声明通过调用 Transport_accept/1 创建的套接字应该继承为监听器套接字设置的选项。第一个进程在执行 Transport_accept/3 时继承选项,但由于某种原因第二个进程没有继承。 您可以使用
检查选项ssl:getopts(ClientSocket,[mode, active])
我不知道为什么会发生这种情况,但解决方法是在新接受的套接字上显式设置选项
ssl:setopts(ClientSocket, [{active,true}, {mode,binary}])
关于ssl - Erlang ssl 非阻塞并行接受器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9624711/