Erlang 套接字发送超时永远不会发生

Posted

技术标签:

【中文标题】Erlang 套接字发送超时永远不会发生【英文标题】:Erlang socket send timeout never happens 【发布时间】:2011-05-18 09:02:01 【问题描述】:

我正在用 Erlang 实现一个与手机客户端对话的 TCP 服务器。 手机经常下线,所以服务器一定能检测到。 因此,我希望服务器在超时的情况下向客户端发送消息,以便在发生超时时关闭连接并将客户端标记为脱机。

我在服务器上使用了这个监听选项:

[certfile, "cert.pem",   
 keyfile, "key.pem",
 reuseaddr, true,   
 active, false,
 send_timeout, 10000]

服务器和手机建立连接后,我将手机切换到飞行模式(关闭所有无线信号),并在服务器上执行ssl:send。发送函数高兴地返回ok,就好像数据包传输成功一样。

我做错了什么?

【问题讨论】:

你从哪里得到 send_timeout 的?查看ssl 模块,我没有看到该选项。 他是从inet 那里得到的。例如,如果使用ssl:connect/4,您可以提供任何套接字选项,包括来自inet 的超时。 【参考方案1】:

您是否在inet 的套接字上设置了send_timeout_close, true 参数?如果没有,套接字将不会关闭,只是返回一个超时错误。还有ssl 吞下您的错误并对其进行处理的风险。

其他几点:

记得检查任何ssl:sendssl:receive 选项的返回值是否有错误。重要的是要知道发送顺利。

ok = ssl:send(Sock, Data),

即使设置了send_timeout,底层 TCP/IP 堆栈实际上也可能接受数据,但由于另一个端点已关闭,因此无法发送数据。当堆栈意识到它从未收到 ACK 时,关闭端口的知识首先到达。

套接字有一个raw 条目类型,在inet 中定义。它允许您设置特定于操作系统的套接字选项。可能会强制操作系统更积极地检测连接丢失。

另一种选择是在 ssl:recv/3 调用中提示所有内容,其中超时表示设备丢失,无论其套接字状态如何。它还具有在另一端检测应用程序故障的优点,因为它不沿着确定的路径前进。无论如何,您都必须这样做才能处理更多请求。

手机客户端也可以行动。如果它通过 SSL 发送消息并且接收从未到达(由于飞行模式) - 那么它知道有问题了。然而,服务器可能不知道这一点。

TCP/IP 提供可靠的、面向连接的流协议。它不能防止突然断开连接。这很重要,因为您的协议必须自行处理断开连接问题。如果您的协议有某种确认或确认,这一点尤其重要。

【讨论】:

也许这就是问题所在。我已经设置了 send_timeout_close 但 ssl:send 总是返回正常。似乎 ssl:send 不等待 ACK,而是依赖于某个系统调用,它一直返回成功。

以上是关于Erlang 套接字发送超时永远不会发生的主要内容,如果未能解决你的问题,请参考以下文章

erlang 发送套接字西里尔文数据

c中的数据报套接字。看起来父进程永远不会绑定

在 Erlang 中通过 tcp 套接字发送元组

Java 客户端/服务器套接字损坏的管道

MongoDB erlang 连接结束

为啥套接字关闭 Erlang