如果达到超时,gen_tcp:recv / 3会关闭套接字吗?

时间:2016-03-03 15:19:18

标签: sockets erlang gen-tcp erlang-ports

我目前有一个服务器处理来自客户端的多个连接,以及使用两个连接连接到服务器的客户端。我的客户端有两个进程分别处理和发送到服务器和从服务器接收,但不是两者。我目前遇到的问题是当我想关闭套接字时,我的阅读过程卡在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没有读取任何内容,则该过程将永远无法收到结束。

1 个答案:

答案 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