在 gen_tcp 文档中有如下说明:
the fact that the send call does not accept a timeout option, is because timeouts on send is handled through the socket optionsend_timeout. the behavior of a send operation with no receiver is in a very high degree defined by the underlying tcp stack, as well as the network infrastructure. if one wants to write code that handles a hanging receiver that might eventually cause the sender to hang on a send call, one writes code like the following.
大致意思为,sender 发送时没有 receiver 的情况,已经通过底层 tcp 协议栈很好的解决了,如果 sender 想使用带 timeout 功能的 send ,则需要在 connect 的时候指定 {send_timeout, xxx} 。
business process <--> client process(connect) <--> server process(accept)
<a href="http://my.oschina.net/moooofly/blog/281993#">?</a>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<code>...</code>
<code>gen_tcp:connect(hostaddress, port, [{active,</code><code>false</code><code>}, {send_timeout, 5000}, {packet,2}]),</code>
<code>loop(sock),</code>
<code>in the loop where requests are handled, we can now detect send timeouts:</code>
<code>loop(sock) -></code>
<code> </code><code>receive</code>
<code> </code><code>%% 这里是来自 business 的消息发送命令</code>
<code> </code><code>{client, send_data, binary} -></code>
<code> </code><code>case</code> <code>gen_tcp:send(sock,[binary]) of</code>
<code> </code><code>%% 这里完成针对 send 的超时处理</code>
<code> </code><code>{error, timeout} -></code>
<code> </code><code>io:</code><code>format</code><code>(</code><code>"send timeout, closing!~n"</code><code>, []),</code>
<code> </code><code>%% 可以针对超时做业务处理</code>
<code> </code><code>handle_send_timeout(), % not implemented here</code>
<code> </code><code>client ! {self(),{error_sending, timeout}},</code>
<code> </code><code>%% usually, it's a good idea to give up</code><code>in</code> <code>case</code> <code>of a</code>
<code> </code><code>%% send timeout, as you never know how much actually</code>
<code> </code><code>%% reached the server, maybe only a packet header?!</code>
<code> </code><code>%% 这里建议直接关闭</code>
<code> </code><code>gen_tcp:close(sock);</code>
<code> </code><code>{error, othersenderror} -></code>
<code> </code><code>io:</code><code>format</code><code>(</code><code>"some other error on socket (~p), closing"</code><code>,</code>
<code> </code><code>[othersenderror]),</code>
<code> </code><code>client ! {self(),{error_sending, othersenderror}},</code>
<code> </code><code>ok -></code>
<code> </code><code>client ! {self(), data_sent},</code>
<code> </code><code>loop(sock)</code>
<code> </code><code>end</code>
<code> </code><code>end.</code>
通常情况下,上述代码足以检测 receive 端的超时问题。大多数协议都会存在某种来自 server 端的确认机制,若存在,则不需要上述代码实现的 send 超时检测。需要使用的唯一场景是应用层协议是单向、无确认机制的情况。