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:send
和ssl: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 套接字发送超时永远不会发生的主要内容,如果未能解决你的问题,请参考以下文章