1gen_tcp(3) Erlang Module Definition gen_tcp(3)
2
3
4
6 gen_tcp - Interface to TCP/IP sockets.
7
9 This module provides functions for communicating with sockets using the
10 TCP/IP protocol.
11
12 The following code fragment is a simple example of a client connecting
13 to a server at port 5678, transferring a binary, and closing the con‐
14 nection:
15
16 client() ->
17 SomeHostInNet = "localhost", % to make it runnable on one machine
18 {ok, Sock} = gen_tcp:connect(SomeHostInNet, 5678,
19 [binary, {packet, 0}]),
20 ok = gen_tcp:send(Sock, "Some Data"),
21 ok = gen_tcp:close(Sock).
22
23 At the other end, a server is listening on port 5678, accepts the con‐
24 nection, and receives the binary:
25
26 server() ->
27 {ok, LSock} = gen_tcp:listen(5678, [binary, {packet, 0},
28 {active, false}]),
29 {ok, Sock} = gen_tcp:accept(LSock),
30 {ok, Bin} = do_recv(Sock, []),
31 ok = gen_tcp:close(Sock),
32 ok = gen_tcp:close(LSock),
33 Bin.
34
35 do_recv(Sock, Bs) ->
36 case gen_tcp:recv(Sock, 0) of
37 {ok, B} ->
38 do_recv(Sock, [Bs, B]);
39 {error, closed} ->
40 {ok, list_to_binary(Bs)}
41 end.
42
43 For more examples, see section Examples.
44
45 Note:
46 Functions that create sockets can take an optional option; {inet_back‐
47 end, Backend} that, if specified, has to be the first option. This se‐
48 lects the implementation backend towards the platform's socket API.
49
50 This is a temporary option that will be ignored in a future release.
51
52 The default is Backend = inet that selects the traditional inet_drv.c
53 driver. The other choice is Backend = socket that selects the new
54 socket module and its NIF implementation.
55
56 The system default can be changed when the node is started with the ap‐
57 plication kernel's configuration variable inet_backend.
58
59 For gen_tcp with inet_backend = socket we have tried to be as "compati‐
60 ble" as possible which has sometimes been impossible. Here is a list of
61 cases when the behaviour of inet-backend inet (default) and socket are
62 different:
63
64 * Non-blocking send
65
66 If a user calling gen_tcp:send/2 with inet_backend = inet, tries to
67 send more data than there is room for in the OS buffers, the "rest
68 data" is buffered by the inet driver (and later sent in the back‐
69 ground). The effect for the user is that the call is non-blocking.
70
71 This is not the effect when inet_backend = socket, since there is
72 no buffering. Instead the user hangs either until all data has been
73 sent or the send_timeout timeout has been reached.
74
75 * Remote close detected by background send.
76
77 An background send will detect a 'remote close' and (the inet
78 driver will) mark the socket as 'closed'. No other action is taken.
79 If the socket has active set to false (passive) at this point and
80 no one is reading, this will not be noticed. But as soon as the
81 socket is "activated" (active set to not false, send/2 is called or
82 recv/2,3 is called), an error message will be sent to the caller or
83 (socket) owner: {tcp_error, Socket, econnreset}. Any data in the OS
84 receive buffers will be lost!
85
86 This behaviour is not replicated by the socket implementation. A
87 send operation will detect a remote close and immediately return
88 this to the caller, but do nothing else. A reader will therefor be
89 able to extract any data from the OS buffers. If the socket is set
90 to active to not false, the data will be received as expected
91 ({tcp, ...} and then a closed message ({tcp_closed, ...} will be
92 received (not an error).
93
94 * The option show_econnreset basically do not work as described when
95 used with inet_backend = socket. The "issue" is that a remote close
96 (as described above) do allow a reader to extract what is in the
97 read buffers before a close is "delivered".
98
99 * The option nodelay is a TCP specific option that is not compatible
100 with domain = local.
101
102 When using inet_backend = socket, trying to create a socket (via
103 listen or connect) with domain = local (for example with option
104 {ifaddr, {local,"/tmp/test"}}) will fail with {error, enotsup}.
105
106 This does not actually work for inet_backend = inet either, but in
107 that case the error is simply ignored, which is a bad idea. We have
108 choosen to not ignore this error for inet_backend = socket.
109
110 * Async shutdown write
111
112 Calling gen_tcp:shutdown(Socket, write | read_write) on a socket
113 created with inet_backend = socket will take immediate effect, un‐
114 like for a socket created with inet_backend = inet.
115
116 See async shutdown write for more info.
117
119 option() =
120 {active, true | false | once | -32768..32767} |
121 {buffer, integer() >= 0} |
122 {delay_send, boolean()} |
123 {deliver, port | term} |
124 {dontroute, boolean()} |
125 {exit_on_close, boolean()} |
126 {header, integer() >= 0} |
127 {high_msgq_watermark, integer() >= 1} |
128 {high_watermark, integer() >= 0} |
129 {keepalive, boolean()} |
130 {linger, {boolean(), integer() >= 0}} |
131 {low_msgq_watermark, integer() >= 1} |
132 {low_watermark, integer() >= 0} |
133 {mode, list | binary} |
134 list | binary |
135 {nodelay, boolean()} |
136 {packet,
137 0 | 1 | 2 | 4 | raw | sunrm | asn1 | cdr | fcgi | line |
138 tpkt | http | httph | http_bin | httph_bin} |
139 {packet_size, integer() >= 0} |
140 {priority, integer() >= 0} |
141 {raw,
142 Protocol :: integer() >= 0,
143 OptionNum :: integer() >= 0,
144 ValueBin :: binary()} |
145 {recbuf, integer() >= 0} |
146 {reuseaddr, boolean()} |
147 {send_timeout, integer() >= 0 | infinity} |
148 {send_timeout_close, boolean()} |
149 {show_econnreset, boolean()} |
150 {sndbuf, integer() >= 0} |
151 {tos, integer() >= 0} |
152 {tclass, integer() >= 0} |
153 {ttl, integer() >= 0} |
154 {recvtos, boolean()} |
155 {recvtclass, boolean()} |
156 {recvttl, boolean()} |
157 {ipv6_v6only, boolean()}
158
159 pktoptions_value() = {pktoptions, inet:ancillary_data()}
160
161 If the platform implements the IPv4 option IP_PKTOPTIONS, or the
162 IPv6 option IPV6_PKTOPTIONS or IPV6_2292PKTOPTIONS for the
163 socket this value is returned from inet:getopts/2 when called
164 with the option name pktoptions.
165
166 Note:
167 This option appears to be VERY Linux specific, and its existence
168 in future Linux kernel versions is also worrying since the op‐
169 tion is part of RFC 2292 which is since long (2003) obsoleted by
170 RFC 3542 that explicitly removes this possibility to get packet
171 information from a stream socket. For comparision: it has ex‐
172 isted in FreeBSD but is now removed, at least since FreeBSD 10.
173
174
175 option_name() =
176 active | buffer | delay_send | deliver | dontroute |
177 exit_on_close | header | high_msgq_watermark |
178 high_watermark | keepalive | linger | low_msgq_watermark |
179 low_watermark | mode | nodelay | packet | packet_size |
180 priority |
181 {raw,
182 Protocol :: integer() >= 0,
183 OptionNum :: integer() >= 0,
184 ValueSpec ::
185 (ValueSize :: integer() >= 0) | (ValueBin :: binary())} |
186 recbuf | reuseaddr | send_timeout | send_timeout_close |
187 show_econnreset | sndbuf | tos | tclass | ttl | recvtos |
188 recvtclass | recvttl | pktoptions | ipv6_v6only
189
190 connect_option() =
191 {fd, Fd :: integer() >= 0} |
192 inet:address_family() |
193 {ifaddr,
194 socket:sockaddr_in() |
195 socket:sockaddr_in6() |
196 inet:socket_address()} |
197 {ip, inet:socket_address()} |
198 {port, inet:port_number()} |
199 {tcp_module, module()} |
200 {netns, file:filename_all()} |
201 {bind_to_device, binary()} |
202 option()
203
204 listen_option() =
205 {fd, Fd :: integer() >= 0} |
206 inet:address_family() |
207 {ifaddr,
208 socket:sockaddr_in() |
209 socket:sockaddr_in6() |
210 inet:socket_address()} |
211 {ip, inet:socket_address()} |
212 {port, inet:port_number()} |
213 {backlog, B :: integer() >= 0} |
214 {tcp_module, module()} |
215 {netns, file:filename_all()} |
216 {bind_to_device, binary()} |
217 option()
218
219 socket()
220
221 As returned by accept/1,2 and connect/3,4.
222
224 accept(ListenSocket) -> {ok, Socket} | {error, Reason}
225
226 accept(ListenSocket, Timeout) -> {ok, Socket} | {error, Reason}
227
228 Types:
229
230 ListenSocket = socket()
231 Returned by listen/2.
232 Timeout = timeout()
233 Socket = socket()
234 Reason = closed | timeout | system_limit | inet:posix()
235
236 Accepts an incoming connection request on a listening socket.
237 Socket must be a socket returned from listen/2. Timeout speci‐
238 fies a time-out value in milliseconds. Defaults to infinity.
239
240 Returns:
241
242 * {ok, Socket} if a connection is established
243
244 * {error, closed} if ListenSocket is closed
245
246 * {error, timeout} if no connection is established within the
247 specified time
248
249 * {error, system_limit} if all available ports in the Erlang
250 emulator are in use
251
252 * A POSIX error value if something else goes wrong, see
253 inet(3) for possible error values
254
255 Packets can be sent to the returned socket Socket using send/2.
256 Packets sent from the peer are delivered as messages (unless
257 {active, false} is specified in the option list for the listen‐
258 ing socket, in which case packets are retrieved by calling
259 recv/2):
260
261 {tcp, Socket, Data}
262
263 Note:
264 The accept call does not have to be issued from the socket owner
265 process. Using version 5.5.3 and higher of the emulator, multi‐
266 ple simultaneous accept calls can be issued from different pro‐
267 cesses, which allows for a pool of acceptor processes handling
268 incoming connections.
269
270
271 close(Socket) -> ok
272
273 Types:
274
275 Socket = socket()
276
277 Closes a TCP socket.
278
279 Note that in most implementations of TCP, doing a close does not
280 guarantee that any data sent is delivered to the recipient be‐
281 fore the close is detected at the remote side. If you want to
282 guarantee delivery of the data to the recipient there are two
283 common ways to achieve this.
284
285 * Use gen_tcp:shutdown(Sock, write) to signal that no more
286 data is to be sent and wait for the read side of the socket
287 to be closed.
288
289 * Use the socket option {packet, N} (or something similar) to
290 make it possible for the receiver to close the connection
291 when it knowns it has received all the data.
292
293 connect(SockAddr, Opts) -> {ok, Socket} | {error, Reason}
294
295 connect(SockAddr, Opts, Timeout) -> {ok, Socket} | {error, Reason}
296
297 Types:
298
299 SockAddr = socket:sockaddr_in() | socket:sockaddr_in6()
300 Opts = [inet:inet_backend() | connect_option()]
301 Timeout = timeout()
302 Socket = socket()
303 Reason = timeout | inet:posix()
304
305 Connects to a server according to SockAddr. This is primarily
306 intended for link local IPv6 addresses (which require the scope-
307 id), socket:sockaddr_in6(). But for completeness, we also sup‐
308 port IPv4, socket:sockaddr_in().
309
310 The options available are the same as for connect/3,4.
311
312 Note:
313 Keep in mind that if the underlying OS connect() call returns a
314 timeout, gen_tcp:connect will also return a timeout (i.e. {er‐
315 ror, etimedout}), even if a larger Timeout was specified.
316
317
318 Note:
319 The default values for options specified to connect can be af‐
320 fected by the Kernel configuration parameter inet_default_con‐
321 nect_options. For details, see inet(3).
322
323
324 connect(Address, Port, Opts) -> {ok, Socket} | {error, Reason}
325
326 connect(Address, Port, Opts, Timeout) ->
327 {ok, Socket} | {error, Reason}
328
329 Types:
330
331 Address = inet:socket_address() | inet:hostname()
332 Port = inet:port_number()
333 Opts = [inet:inet_backend() | connect_option()]
334 Timeout = timeout()
335 Socket = socket()
336 Reason = timeout | inet:posix()
337
338 Connects to a server on TCP port Port on the host with IP ad‐
339 dress Address. Argument Address can be a hostname or an IP ad‐
340 dress.
341
342 The following options are available:
343
344 {ip, Address}:
345 If the host has many network interfaces, this option speci‐
346 fies which one to use.
347
348 {ifaddr, Address}:
349 Same as {ip, Address}. If the host has many network inter‐
350 faces, this option specifies which one to use.
351
352 However, if this instead is an socket:sockaddr_in() or
353 socket:sockaddr_in6() this takes precedence over any value
354 previously set with the ip and port options. If these op‐
355 tions (ip or/and port) however comes after this option, they
356 may be used to update their corresponding fields of this op‐
357 tions (for ip, the addr field, and for port, the port
358 field).
359
360 {fd, integer() >= 0}:
361 If a socket has somehow been connected without using
362 gen_tcp, use this option to pass the file descriptor for it.
363 If {ip, Address} and/or {port, port_number()} is combined
364 with this option, the fd is bound to the specified interface
365 and port before connecting. If these options are not speci‐
366 fied, it is assumed that the fd is already bound appropri‐
367 ately.
368
369 inet:
370 Sets up the socket for IPv4.
371
372 inet6:
373 Sets up the socket for IPv6.
374
375 local:
376 Sets up a Unix Domain Socket. See inet:local_address()
377
378 {port, Port}:
379 Specifies which local port number to use.
380
381 {tcp_module, module()}:
382 Overrides which callback module is used. Defaults to
383 inet_tcp for IPv4 and inet6_tcp for IPv6.
384
385 Opt:
386 See inet:setopts/2.
387
388 Packets can be sent to the returned socket Socket using send/2.
389 Packets sent from the peer are delivered as messages:
390
391 {tcp, Socket, Data}
392
393 If the socket is in {active, N} mode (see inet:setopts/2 for de‐
394 tails) and its message counter drops to 0, the following message
395 is delivered to indicate that the socket has transitioned to
396 passive ({active, false}) mode:
397
398 {tcp_passive, Socket}
399
400 If the socket is closed, the following message is delivered:
401
402 {tcp_closed, Socket}
403
404 If an error occurs on the socket, the following message is de‐
405 livered (unless {active, false} is specified in the option list
406 for the socket, in which case packets are retrieved by calling
407 recv/2):
408
409 {tcp_error, Socket, Reason}
410
411 The optional Timeout parameter specifies a time-out in millisec‐
412 onds. Defaults to infinity.
413
414 Note:
415 Keep in mind that if the underlying OS connect() call returns a
416 timeout, gen_tcp:connect will also return a timeout (i.e. {er‐
417 ror, etimedout}), even if a larger Timeout was specified.
418
419
420 Note:
421 The default values for options specified to connect can be af‐
422 fected by the Kernel configuration parameter inet_default_con‐
423 nect_options. For details, see inet(3).
424
425
426 controlling_process(Socket, Pid) -> ok | {error, Reason}
427
428 Types:
429
430 Socket = socket()
431 Pid = pid()
432 Reason = closed | not_owner | badarg | inet:posix()
433
434 Assigns a new controlling process Pid to Socket. The controlling
435 process is the process that receives messages from the socket.
436 If called by any other process than the current controlling
437 process, {error, not_owner} is returned. If the process identi‐
438 fied by Pid is not an existing local pid, {error, badarg} is re‐
439 turned. {error, badarg} may also be returned in some cases when
440 Socket is closed during the execution of this function.
441
442 If the socket is set in active mode, this function will transfer
443 any messages in the mailbox of the caller to the new controlling
444 process. If any other process is interacting with the socket
445 while the transfer is happening, the transfer may not work cor‐
446 rectly and messages may remain in the caller's mailbox. For in‐
447 stance changing the sockets active mode before the transfer is
448 complete may cause this.
449
450 listen(Port, Options) -> {ok, ListenSocket} | {error, Reason}
451
452 Types:
453
454 Port = inet:port_number()
455 Options = [inet:inet_backend() | listen_option()]
456 ListenSocket = socket()
457 Reason = system_limit | inet:posix()
458
459 Sets up a socket to listen on port Port on the local host.
460
461 If Port == 0, the underlying OS assigns an available port num‐
462 ber, use inet:port/1 to retrieve it.
463
464 The following options are available:
465
466 list:
467 Received Packet is delivered as a list.
468
469 binary:
470 Received Packet is delivered as a binary.
471
472 {backlog, B}:
473 B is an integer >= 0. The backlog value defines the maximum
474 length that the queue of pending connections can grow to.
475 Defaults to 5.
476
477 inet6:
478 Sets up the socket for IPv6.
479
480 inet:
481 Sets up the socket for IPv4.
482
483 {fd, Fd}:
484 If a socket has somehow been connected without using
485 gen_tcp, use this option to pass the file descriptor for it.
486
487 {ip, Address}:
488 If the host has many network interfaces, this option speci‐
489 fies which one to listen on.
490
491 {port, Port}:
492 Specifies which local port number to use.
493
494 {ifaddr, Address}:
495 Same as {ip, Address}. If the host has many network inter‐
496 faces, this option specifies which one to use.
497
498 However, if this instead is an socket:sockaddr_in() or
499 socket:sockaddr_in6() this takes precedence over any value
500 previously set with the ip and port options. If these op‐
501 tions (ip or/and port) however comes after this option, they
502 may be used to update their corresponding fields of this op‐
503 tions (for ip, the addr field, and for port, the port
504 field).
505
506 {tcp_module, module()}:
507 Overrides which callback module is used. Defaults to
508 inet_tcp for IPv4 and inet6_tcp for IPv6.
509
510 Opt:
511 See inet:setopts/2.
512
513 The returned socket ListenSocket should be used in calls to ac‐
514 cept/1,2 to accept incoming connection requests.
515
516 Note:
517 The default values for options specified to listen can be af‐
518 fected by the Kernel configuration parameter inet_default_lis‐
519 ten_options. For details, see inet(3).
520
521
522 recv(Socket, Length) -> {ok, Packet} | {error, Reason}
523
524 recv(Socket, Length, Timeout) -> {ok, Packet} | {error, Reason}
525
526 Types:
527
528 Socket = socket()
529 Length = integer() >= 0
530 Timeout = timeout()
531 Packet = string() | binary() | HttpPacket
532 Reason = closed | timeout | inet:posix()
533 HttpPacket = term()
534 See the description of HttpPacket in erlang:decode_packet/3
535 in ERTS.
536
537 Receives a packet from a socket in passive mode. A closed socket
538 is indicated by return value {error, closed}.
539
540 Argument Length is only meaningful when the socket is in raw
541 mode and denotes the number of bytes to read. If Length is 0,
542 all available bytes are returned. If Length > 0, exactly Length
543 bytes are returned, or an error; possibly discarding less than
544 Length bytes of data when the socket is closed from the other
545 side.
546
547 The optional Timeout parameter specifies a time-out in millisec‐
548 onds. Defaults to infinity.
549
550 send(Socket, Packet) -> ok | {error, Reason}
551
552 Types:
553
554 Socket = socket()
555 Packet = iodata()
556 Reason = closed | {timeout, RestData} | inet:posix()
557 RestData = binary()
558
559 Sends a packet on a socket.
560
561 There is no send call with a time-out option, use socket option
562 send_timeout if time-outs are desired. See section Examples.
563
564 The return value {error, {timeout, RestData}} can only be re‐
565 turned when inet_backend = socket.
566
567 Note:
568 Non-blocking send.
569
570 If the user tries to send more data than there is room for in
571 the OS send buffers, the 'rest data' is put into (inet driver)
572 internal buffers and later sent in the background. The function
573 immediately returns ok (not informing the caller that not all of
574 the data was actually sent). Any issue while sending the 'rest
575 data' is maybe returned later.
576
577 When using inet_backend = socket, the behaviour is different.
578 There is no buffering done (like the inet-driver does), instead
579 the caller will "hang" until all of the data has been sent or
580 send timeout (as specified by the send_timeout option) expires
581 (the function can hang even when using 'inet' backend if the in‐
582 ternal buffers are full).
583
584 If this happens when using packet =/= raw, we have a partial
585 package written. A new package therefor must not be written at
586 this point, as there is no way for the peer to distinguish this
587 from the data portion of the current package. Instead, set pack‐
588 age to raw, send the rest data (as raw data) and then set pack‐
589 age to the wanted package type again.
590
591
592 shutdown(Socket, How) -> ok | {error, Reason}
593
594 Types:
595
596 Socket = socket()
597 How = read | write | read_write
598 Reason = inet:posix()
599
600 Closes a socket in one or two directions.
601
602 How == write means closing the socket for writing, reading from
603 it is still possible.
604
605 If How == read or there is no outgoing data buffered in the
606 Socket port, the socket is shut down immediately and any error
607 encountered is returned in Reason.
608
609 If there is data buffered in the socket port, the attempt to
610 shutdown the socket is postponed until that data is written to
611 the kernel socket send buffer. If any errors are encountered,
612 the socket is closed and {error, closed} is returned on the next
613 recv/2 or send/2.
614
615 Option {exit_on_close, false} is useful if the peer has done a
616 shutdown on the write side.
617
618 Note:
619 Async shutdown write (write or read_write).
620
621 If the shutdown attempt is made while the inet-driver is sending
622 buffered data in the background, the shutdown is postponed until
623 all buffered data has been sent. The function immediately re‐
624 turns ok and the caller is not informed (that the shutdown has
625 not yet been performed).
626
627 When using inet_backend = socket, the behaviour is different. A
628 shutdown with How == write | read_write, the operation will take
629 immediate effect (unlike the inet-driver, which basically saves
630 the operation for later).
631
632
634 The following example illustrates use of option {active,once} and mul‐
635 tiple accepts by implementing a server as a number of worker processes
636 doing accept on a single listening socket. Function start/2 takes the
637 number of worker processes and the port number on which to listen for
638 incoming connections. If LPort is specified as 0, an ephemeral port
639 number is used, which is why the start function returns the actual port
640 number allocated:
641
642 start(Num,LPort) ->
643 case gen_tcp:listen(LPort,[{active, false},{packet,2}]) of
644 {ok, ListenSock} ->
645 start_servers(Num,ListenSock),
646 {ok, Port} = inet:port(ListenSock),
647 Port;
648 {error,Reason} ->
649 {error,Reason}
650 end.
651
652 start_servers(0,_) ->
653 ok;
654 start_servers(Num,LS) ->
655 spawn(?MODULE,server,[LS]),
656 start_servers(Num-1,LS).
657
658 server(LS) ->
659 case gen_tcp:accept(LS) of
660 {ok,S} ->
661 loop(S),
662 server(LS);
663 Other ->
664 io:format("accept returned ~w - goodbye!~n",[Other]),
665 ok
666 end.
667
668 loop(S) ->
669 inet:setopts(S,[{active,once}]),
670 receive
671 {tcp,S,Data} ->
672 Answer = process(Data), % Not implemented in this example
673 gen_tcp:send(S,Answer),
674 loop(S);
675 {tcp_closed,S} ->
676 io:format("Socket ~w closed [~w]~n",[S,self()]),
677 ok
678 end.
679
680 Example of a simple client:
681
682 client(PortNo,Message) ->
683 {ok,Sock} = gen_tcp:connect("localhost",PortNo,[{active,false},
684 {packet,2}]),
685 gen_tcp:send(Sock,Message),
686 A = gen_tcp:recv(Sock,0),
687 gen_tcp:close(Sock),
688 A.
689
690 The send call does not accept a time-out option because time-outs on
691 send is handled through socket option send_timeout. The behavior of a
692 send operation with no receiver is mainly defined by the underlying TCP
693 stack and the network infrastructure. To write code that handles a
694 hanging receiver that can eventually cause the sender to hang on a send
695 do like the following.
696
697 Consider a process that receives data from a client process to be for‐
698 warded to a server on the network. The process is connected to the
699 server through TCP/IP and does not get any acknowledge for each message
700 it sends, but has to rely on the send time-out option to detect that
701 the other end is unresponsive. Option send_timeout can be used when
702 connecting:
703
704 {ok,Sock} = gen_tcp:connect(HostAddress, Port,
705 [{active,false},
706 {send_timeout, 5000},
707 {packet,2}]),
708 loop(Sock), % See below
709
710 In the loop where requests are handled, send time-outs can now be de‐
711 tected:
712
713 loop(Sock) ->
714 receive
715 {Client, send_data, Binary} ->
716 case gen_tcp:send(Sock,[Binary]) of
717 {error, timeout} ->
718 io:format("Send timeout, closing!~n",
719 []),
720 handle_send_timeout(), % Not implemented here
721 Client ! {self(),{error_sending, timeout}},
722 %% Usually, it's a good idea to give up in case of a
723 %% send timeout, as you never know how much actually
724 %% reached the server, maybe only a packet header?!
725 gen_tcp:close(Sock);
726 {error, OtherSendError} ->
727 io:format("Some other error on socket (~p), closing",
728 [OtherSendError]),
729 Client ! {self(),{error_sending, OtherSendError}},
730 gen_tcp:close(Sock);
731 ok ->
732 Client ! {self(), data_sent},
733 loop(Sock)
734 end
735 end.
736
737 Usually it suffices to detect time-outs on receive, as most protocols
738 include some sort of acknowledgment from the server, but if the proto‐
739 col is strictly one way, option send_timeout comes in handy.
740
741
742
743Ericsson AB kernel 8.3.2 gen_tcp(3)