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

Posted

技术标签:

【中文标题】如果达到超时,gen_tcp:recv/3 是不是会关闭套接字?【英文标题】:Does gen_tcp:recv/3 closes the socket if the timeout is reached?如果达到超时,gen_tcp:recv/3 是否会关闭套接字? 【发布时间】:2016-06-17 00:11:23 【问题描述】:

我目前有一个服务器来处理来自客户端的多个连接,以及使用两个连接连接到服务器的客户端。我的客户端有两个进程分别处理与服务器之间的发送和接收,但不能同时处理两者。我目前遇到的问题是当我想关闭套接字时,我的阅读过程卡在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】:

当然,gen_tcp:recv/3 超时设置为infinity 不会关闭套接字:) 请参阅official documentation。

编辑:

来自文档:

此函数以被动模式从套接字接收数据包。

查看documentation for setopts/2 以了解被动模式和主动模式之间的区别。特别是:

如果值为 false(被动模式),则进程必须通过调用 gen_tcp:recv/2,3 显式接收传入数据。

你的进程一次只能做一件事——要么监听来自另一个进程的关闭消息,要么等待 TCP 数据包。您可以尝试使用gen_tcp:controlling_process/2,但我不知道详细信息。另一种解决方案是在单独的(第三个)链接进程中处理recv/3,并在收到关闭时终止该进程。

更好的方法是使用活动套接字,请参阅official documentation 中的示例部分以获取有关如何执行此操作的一些指南。

在我看来,最好的方法是使用 OTP gen_server 在同一进程中同时处理 close 消息和传入的 TCP 数据包。 Erlang and OTP in Action 书中有一个关于如何实现它的优秀教程,这里是 code example on Github。

【讨论】:

我知道它没有,但如果它设置为 infinity 这意味着我无法检查 read/2 收到的任何内容(如“read”或“close”),因为它正在等待来自服务器的消息。这就是为什么我想设置一个超时,因为这将导致进程调用自身(读取/2)并处理其可能包含“关闭”的邮箱。 我知道你知道 :) 你的问题不清楚。您问:是否有可能进行不关闭套接字的 gen_tcp:recv/3 调用。您可能希望能够在同一进程中接收 tcp 或您的消息,这是不可能的,因为正如文档所述,“此函数以被动模式从套接字接收数据包。”。我将添加一个编辑以提供一些信息如何处理。

以上是关于如果达到超时,gen_tcp:recv/3 是不是会关闭套接字?的主要内容,如果未能解决你的问题,请参考以下文章

确定 $.ajax 错误是不是超时

确定 $.ajax 错误是不是超时

确定 $.ajax 错误是不是超时

如果达到 Wait_For_Message 超时,则发送消息 Discord Py

超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。

[转]超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。