我目前有一个服务器处理来自客户端的多个连接,以及使用两个连接连接到服务器的客户端。我的客户端有两个进程分别处理和发送到服务器和从服务器接收,但不是两者。我目前遇到的问题是当我想关闭套接字时,我的阅读过程卡在gen_tcp:recv/2
块上。如果我发出超时,则在达到超时时关闭套接字。我的问题是,是否可以进行不会关闭套接字的gen_tcp:recv/3
调用
这就是我的阅读过程。
read(Socket, Control) ->
Control ! ok,
receive
read ->
case gen_tcp:recv(Socket, 0) of
{ok, Data} ->
%% handling for messages;
Other ->
io:format(Other)
end,
read(self()), %% this sends "read" to itself with "!"
read(Socket, Control);
{error, Reason} ->
io:format(Reason)
end;
close ->
io:format("Closing Reading Socket.~n"),
gen_tcp:close(Socket)
end.
正如您在此处所见,如果recv/2
没有读取任何内容,则该过程将永远无法收到结束。
答案 0 :(得分:1)
当然,超时设置为gen_tcp:recv/3
的{{1}}不会关闭套接字:)请参阅official documentation。
修改强>
来自文档:
此函数以被动模式从套接字接收数据包。
检查documentation for setopts/2
以了解被动和主动模式之间的区别。特别是:
如果值为false(被动模式),则进程必须通过调用gen_tcp:recv / 2,3显式接收传入数据。
您的进程一次只能执行一项操作 - 侦听来自其他进程的关闭消息或等待TCP数据包。您可以尝试使用infinity
,但我不知道详细信息。另一种解决方案是在单独的(第三个)链接过程中处理gen_tcp:controlling_process/2
并在收到关闭时终止该过程。
更好的方法是使用活动套接字,请参阅official documentation中的示例部分,了解如何执行此操作。
我认为最好的方法是使用OTP recv/3
来处理同一进程中的gen_server
消息和传入的TCP数据包。 Erlang and OTP in Action一书中有一篇关于如何实现它的优秀教程,这里是code example on Github。