我正在实现一个 gen_server 作为一个 gen_server,它作为一个 ssl 身份验证服务器的接口。如果收到的数据包错误(例如错误的用户名和密码),ssl 服务器将切断连接。连接必须是持久的。
在我的 gen_server 中,我使用 handle_cast/2 打开与服务器的 ssl 连接:
handle_cast(connect, State) ->
......
case ssl:connect(Address, Port, Options, Timeout) of
{ok, NewSocket} ->
{noreply, State#state{socket=NewSocket}};
{error, Reason} ->
gen_server:cast(?SERVER, connect),
{noreply, State#state{socket=undefined}};
然后我在 handle_cast/2 中等待其他其他消息,例如可以使用:
gen_server:cast(Pid, {authenticate, User, Password}).
每当我收到这样的强制转换消息时,我都会生成一个新函数,该函数使用 gen_server:call/3 从服务器状态恢复 SSL 套接字并将身份验证消息发送到 SSL 服务器。如果发送部分返回错误,我会尝试重新连接,否则我会在套接字上读取一段时间,以确保套接字不会关闭,如果是,我会重新连接。
send_auth(_, _, 0) ->
{error, max_num_reached};
send_auth(User, Password, Num) ->
Socket = gen_server:call(?SERVER, socket),
%% also a check that socket is not 'undefined'
case ssl:send(Socket, AuthMessage) of
ok ->
case ssl:recv(Socket, 0, 2000) of
{error, timeout} ->
ok;
_ ->
gen_server:cast(?SERVER, connect),
send_auth(User, Password, Num-1)
end,
{error, closed} ->
gen_server:cast(?SERVER, connect),
send_auth(User, Password, Num-1)
end.
我做了很多测试,但每次,如果一条消息(不是最后一条)是错误的,则实际上没有传递以下消息。
如何允许所有有效的身份验证消息都传递到身份验证服务器?此外,如何确保服务器仅在尚未尝试连接时才会连接?否则就像 DOS 攻击一样!