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