天天看點

【原創】Erlang 的 gen_tcp:send 為什麼沒有 timeout 選項

在 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) -&gt;</code>

<code>    </code><code>receive</code>

<code>        </code><code>%% 這裡是來自 business 的消息發送指令</code>

<code>        </code><code>{client, send_data, binary} -&gt;</code>

<code>            </code><code>case</code> <code>gen_tcp:send(sock,[binary]) of</code>

<code>                </code><code>%% 這裡完成針對 send 的逾時處理</code>

<code>                </code><code>{error, timeout} -&gt;</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} -&gt;</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 -&gt;</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 逾時檢測。需要使用的唯一場景是應用層協定是單向、無确認機制的情況。