1 '\"
2 .\" This file and its contents are supplied under the terms of the
3 .\" Common Development and Distribution License ("CDDL"), version 1.0.
4 .\" You may only use this file in accordance with the terms of version
5 .\" 1.0 of the CDDL.
6 .\"
7 .\" A full copy of the text of the CDDL should have accompanied this
8 .\" source. A copy of the CDDL is also available via the Internet at
9 .\" http://www.illumos.org/license/CDDL.
10 .\"
11 .\"
12 .\" Copyright (c) 2006, Sun Microsystems, Inc. All Rights Reserved.
13 .\" Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved.
14 .\" Copyright 2019 Joyent, Inc.
15 .\" Copyright 1989 AT&T
16 .\"
17 .Dd "Jan 07, 2019"
18 .Dt TCP 7P
19 .Os
20 .Sh NAME
21 .Nm tcp ,
22 .Nm TCP
23 .Nd Internet Transmission Control Protocol
24 .Sh SYNOPSIS
25 .In sys/socket.h
26 .In netinet/in.h
27 .In netinet/tcp.h
28 .Bd -literal
29 s = socket(AF_INET, SOCK_STREAM, 0);
30 s = socket(AF_INET6, SOCK_STREAM, 0);
31 t = t_open("/dev/tcp", O_RDWR);
32 t = t_open("/dev/tcp6", O_RDWR);
33 .Ed
34 .Sh DESCRIPTION
35 TCP is the virtual circuit protocol of the Internet protocol family.
36 It provides reliable, flow-controlled, in-order, two-way transmission of data.
37 It is a byte-stream protocol layered above the Internet Protocol
38 .Po Sy IP Pc ,
39 or the Internet Protocol Version 6
40 .Po Sy IPv6 Pc ,
41 the Internet protocol family's
42 internetwork datagram delivery protocol.
43 .Pp
44 Programs can access TCP using the socket interface as a
45 .Dv SOCK_STREAM
46 socket type, or using the Transport Level Interface
47 .Po Sy TLI Pc
48 where it supports the connection-oriented
49 .Po Dv BT_COTS_ORD Pc
50 service type.
51 .Pp
52 A checksum over all data helps TCP provide reliable communication.
53 Using a window-based flow control mechanism that makes use of positive
54 acknowledgements, sequence numbers, and a retransmission strategy, TCP can
55 usually recover when datagrams are damaged, delayed, duplicated or delivered
56 out of order by the underlying medium.
57 .Pp
58 TCP provides several socket options, defined in
59 .In netinet/tcp.h
60 and described throughout this document,
61 which may be set using
62 .Xr setsockopt 3SOCKET
63 and read using
64 .Xr getsockopt 3SOCKET .
65 The
66 .Fa level
67 argument for these calls is the protocol number for TCP, available from
68 .Xr getprotobyname 3SOCKET .
69 IP level options may also be used with TCP.
70 See
71 .Xr ip 7P
72 and
73 .Xr ip6 7P .
74 .Ss "Listening And Connecting"
75 TCP uses IP's host-level addressing and adds its own per-host
76 collection of
77 .Dq port addresses .
78 The endpoints of a TCP connection are
79 identified by the combination of an IPv4 or IPv6 address and a TCP
80 port number.
81 Although other protocols, such as the User Datagram Protocol
82 .Po Sy UDP Pc ,
83 may use the same host and port address format, the port space of these
84 protocols is distinct.
85 See
86 .Xr inet 7P
87 and
88 .Xr inet6 7P
89 for details on
90 the common aspects of addressing in the Internet protocol family.
91 .Pp
92 Sockets utilizing TCP are either
93 .Dq active
94 or
95 .Dq passive .
96 Active sockets
97 initiate connections to passive sockets.
98 Passive sockets must have their local IPv4 or IPv6 address and TCP port number
99 bound with the
100 .Xr bind 3SOCKET
101 system call after the socket is created.
102 If an active socket has not been bound by the time
103 .Xr connect 3SOCKET
104 is called, then the operating system will choose a local address and port for
105 the application.
106 By default, TCP sockets are active.
107 A passive socket is created by calling the
108 .Xr listen 3SOCKET
109 system call after binding, which establishes a queueing parameter for the
110 passive socket.
111 Connections to the passive socket can then be received using the
112 .Xr accept 3SOCKET
113 system call.
114 Active sockets use the
115 .Xr connect 3SOCKET
116 call after binding to initiate connections.
117 .Pp
118 If incoming connection requests include an IP source route option, then the
119 reverse source route will be used when responding.
120 .Pp
121 By using the special value
122 .Dv INADDR_ANY
123 with IPv4, or the unspecified
124 address (all zeroes) with IPv6, the local IP address can be left
125 unspecified in the
126 .Fn bind
127 call by either active or passive TCP
128 sockets.
129 This feature is usually used if the local address is either unknown or
130 irrelevant.
131 If left unspecified, the local IP address will be bound at connection time to
132 the address of the network interface used to service the connection.
133 For passive sockets, this is the destination address used by the connecting
134 peer.
135 For active sockets, this is usually an address on the same subnet as the
136 destination or default gateway address, although the rules can be more complex.
137 See
138 .Sy "Source Address Selection"
139 in
140 .Xr inet6 7P
141 for a detailed discussion of how this works in IPv6.
142 .Pp
143 Note that no two TCP sockets can be bound to the same port unless the bound IP
144 addresses are different.
145 IPv4
146 .Dv INADDR_ANY
147 and IPv6 unspecified addresses compare as equal to any IPv4 or IPv6 address.
148 For example, if a socket is bound to
149 .Dv INADDR_ANY
150 or the unspecified address and port
151 .Em N ,
152 no other socket can bind to port
153 .Em N ,
154 regardless of the binding address.
155 This special consideration of
156 .Dv INADDR_ANY
157 and the unspecified address can be changed using the socket option
158 .Dv SO_REUSEADDR .
159 If
160 .Dv SO_REUSEADDR
161 is set on a socket doing a bind, IPv4
162 .Dv INADDR_ANY
163 and the IPv6 unspecified address do not compare as equal to any IP address.
164 This means that as long as the two sockets are not both bound to
165 .Dv INADDR_ANY ,
166 the unspecified address, or the same IP address, then the two sockets can be
167 bound to the same port.
168 .Pp
169 If an application does not want to allow another socket using the
170 .Dv SO_REUSEADDR
171 option to bind to a port its socket is bound to, the
172 application can set the socket-level
173 .Po Dv SOL_SOCKET Pc
174 option
175 .Dv SO_EXCLBIND
176 on a socket.
177 The
178 option values of 0 and 1 mean enabling and disabling the option respectively.
179 Once this option is enabled on a socket, no other socket can be bound to the
180 same port.
181 .Ss "Sending And Receiving Data"
182 Once a connection has been established, data can be exchanged using the
183 .Xr read 2
184 and
185 .Xr write 2
186 system calls.
187 If, after sending data, the local TCP receives no acknowledgements from its
188 peer for a period of time (for example, if the remote machine crashes), the
189 connection is closed and an error is returned.
190 .Pp
191 When a peer is sending data, it will only send up to the advertised
192 .Dq receive window ,
193 which is determined by how much more data the recipient can fit in its buffer.
194 Applications can use the socket-level option
195 .Dv SO_RCVBUF
196 to increase or decrease the receive buffer size.
197 Similarly, the socket-level option
198 .Dv SO_SNDBUF
199 can be used to allow TCP to buffer more unacknowledged and unsent data locally.
200 .Pp
201 Under most circumstances, TCP will send data when it is written by the
202 application.
203 When outstanding data has not yet been acknowledged, though, TCP will gather
204 small amounts of output to be sent as a single packet once an acknowledgement
205 has been received.
206 Usually referred to as Nagle's Algorithm (RFC 896), this behavior helps prevent
207 flooding the network with many small packets.
208 .Pp
209 However, for some highly interactive clients (such as remote shells or
210 windowing systems that send a stream of keypresses or mouse events), this
211 batching may cause significant delays.
212 To disable this behavior, TCP provides a boolean socket option,
213 .Dv TCP_NODELAY .
214 .Pp
215 Conversely, for other applications, it may be desirable for TCP not to send out
216 any data until a full TCP segment can be sent.
217 To enable this behavior, an application can use the TCP-level socket option
218 .Dv TCP_CORK .
219 When set to a non-zero value, TCP will only send out a full TCP segment.
220 When
221 .Dv TCP_CORK
222 is set to zero after it has been enabled, all currently buffered data is sent
223 out (as permitted by the peer's receive window and the current congestion
224 window).
225 .Pp
226 TCP provides an urgent data mechanism, which may be invoked using the
227 out-of-band provisions of
228 .Xr send 3SOCKET .
229 The caller may mark one byte as
230 .Dq urgent
231 with the
232 .Dv MSG_OOB
233 flag to
234 .Xr send 3SOCKET .
235 This sets an
236 .Dq urgent pointer
237 pointing to this byte in the TCP stream.
238 The receiver on the other side of the stream is notified of the urgent data by a
239 .Dv SIGURG
240 signal.
241 The
242 .Dv SIOCATMARK
243 .Xr ioctl 2
244 request returns a value indicating whether the stream is at the urgent mark.
245 Because the system never returns data across the urgent mark in a single
246 .Xr read 2
247 call, it is possible to
248 advance to the urgent data in a simple loop which reads data, testing the
249 socket with the
250 .Dv SIOCATMARK
251 .Fn ioctl
252 request, until it reaches the mark.
253 .Ss "Congestion Control"
254 TCP follows the congestion control algorithm described in RFC 2581, and
255 also supports the initial congestion window (cwnd) changes in RFC 3390.
256 The initial cwnd calculation can be overridden by the socket option
257 .Dv TCP_INIT_CWND .
258 An application can use this option to set the initial cwnd to a
259 specified number of TCP segments.
260 This applies to the cases when the connection
261 first starts and restarts after an idle period.
262 The process must have the
263 .Dv PRIV_SYS_NET_CONFIG
264 privilege if it wants to specify a number greater than that
265 calculated by RFC 3390.
266 .Pp
267 The operating system also provides alternative algorithms that may be more
268 appropriate for your application, including the CUBIC congestion control
269 algorithm described in RFC 8312.
270 These can be configured system-wide using
271 .Xr ipadm 1M ,
272 or on a per-connection basis with the TCP-level socket option
273 .Dv TCP_CONGESTION ,
274 whose argument is the name of the algorithm to use
275 .Pq for example Dq cubic .
276 If the requested algorithm does not exist, then
277 .Fn setsockopt
278 will fail, and
279 .Va errno
280 will be set to
281 .Er ENOENT .
282 .Ss "TCP Keep-Alive"
283 Since TCP determines whether a remote peer is no longer reachable by timing out
284 waiting for acknowledgements, a host that never sends any new data may never
285 notice a peer that has gone away.
286 While consumers can avoid this problem by sending their own periodic heartbeat
287 messages (Transport Layer Security does this, for example),
288 TCP describes an optional keep-alive mechanism in RFC 1122.
289 Applications can enable it using the socket-level option
290 .Dv SO_KEEPALIVE .
291 When enabled, the first keep-alive probe is sent out after a TCP connection is
292 idle for two hours.
293 If the peer does not respond to the probe within eight minutes, the TCP
294 connection is aborted.
295 An application can alter the probe behavior using the following TCP-level
296 socket options:
297 .Bl -tag -offset indent -width 16m
298 .It Dv TCP_KEEPALIVE_THRESHOLD
299 Determines the interval for sending the first probe.
300 The option value is specified as an unsigned integer in milliseconds.
301 The system default is controlled by the TCP
302 .Nm ndd
303 parameter
304 .Cm tcp_keepalive_interval .
305 The minimum value is ten seconds.
306 The maximum is ten days, while the default is two hours.
307 .It Dv TCP_KEEPALIVE_ABORT_THRESHOLD
308 If TCP does not receive a response to the probe, then this option determines
309 how long to wait before aborting a TCP connection.
310 The option value is an unsigned integer in milliseconds.
311 The value zero indicates that TCP should never time
312 out and abort the connection when probing.
313 The system default is controlled by the TCP
314 .Nm ndd
315 parameter
316 .Sy tcp_keepalive_abort_interval .
317 The default is eight minutes.
318 .It Dv TCP_KEEPIDLE
319 This option, like
320 .Dv TCP_KEEPALIVE_THRESHOLD ,
321 determines the interval for sending the first probe, except that
322 the option value is an unsigned integer in
323 .Sy seconds .
324 It is provided primarily for compatibility with other Unix flavors.
325 .It Dv TCP_KEEPCNT
326 This option specifies the number of keep-alive probes that should be sent
327 without any response from the peer before aborting the connection.
328 .It Dv TCP_KEEPINTVL
329 This option specifies the interval in seconds between successive,
330 unacknowledged keep-alive probes.
331 .El
332 .Ss "Additional Configuration"
333 illumos supports TCP Extensions for High Performance (RFC 7323)
334 which includes the window scale and timestamp options, and Protection Against
335 Wrap Around Sequence Numbers
336 .Po Sy PAWS Pc .
337 Note that if timestamps are negotiated on
338 a connection, received segments without timestamps on that connection are
339 silently dropped per the suggestion in the RFC. illumos also supports Selective
340 Acknowledgment
341 .Po Sy SACK Pc
342 capabilities (RFC 2018) and Explicit Congestion
343 Notification
344 .Po Sy ECN Pc
345 mechanism (RFC 3168).
346 .Pp
347 Turn on the window scale option in one of the following ways:
348 .Bl -bullet -offset indent -width 4m
349 .It
350 An application can set
351 .Dv SO_SNDBUF
352 or
353 .Dv SO_RCVBUF
354 size in the
355 .Fn setsockopt
356 option to be larger than 64K.
357 This must be done
358 .Em before
359 the program calls
360 .Fn listen
361 or
362 .Fn connect ,
363 because the window scale
364 option is negotiated when the connection is established.
365 Once the connection
366 has been made, it is too late to increase the send or receive window beyond the
367 default TCP limit of 64K.
368 .It
369 For all applications, use
370 .Xr ndd 1M
371 to modify the configuration parameter
372 .Cm tcp_wscale_always .
373 If
374 .Cm tcp_wscale_always
375 is set to
376 .Sy 1 ,
377 the
378 window scale option will always be set when connecting to a remote system.
379 If
380 .Cm tcp_wscale_always
381 is
382 .Sy 0 ,
383 the window scale option will be set only if
384 the user has requested a send or receive window larger than 64K.
385 The default value of
386 .Cm tcp_wscale_always
387 is
388 .Sy 1 .
389 .It
390 Regardless of the value of
391 .Cm tcp_wscale_always ,
392 the window scale option
393 will always be included in a connect acknowledgement if the connecting system
394 has used the option.
395 .El
396 .Pp
397 Turn on SACK capabilities in the following way:
398 .Bl -bullet -offset indent -width 4m
399 .It
400 Use
401 .Nm ndd
402 to modify the configuration parameter
403 .Cm tcp_sack_permitted .
404 If
405 .Cm tcp_sack_permitted
406 is set to
407 .Sy 0 ,
408 TCP will not accept SACK or send out SACK information.
409 If
410 .Cm tcp_sack_permitted
411 is
412 set to
413 .Sy 1 ,
414 TCP will not initiate a connection with SACK permitted option in the
415 .Sy SYN
416 segment, but will respond with SACK permitted option in the
417 .Sy SYN|ACK
418 segment if an incoming connection request has the SACK permitted option.
419 This means that TCP will only accept SACK information if the other side of the
420 connection also accepts SACK information.
421 If
422 .Cm tcp_sack_permitted
423 is set to
424 .Sy 2 ,
425 it will both initiate and accept connections with SACK information.
426 The default for
427 .Cm tcp_sack_permitted
428 is
429 .Sy 2
430 .Pq active enabled .
431 .El
432 .Pp
433 Turn on the TCP ECN mechanism in the following way:
434 .Bl -bullet -offset indent -width 4m
435 .It
436 Use
437 .Nm ndd
438 to modify the configuration parameter
439 .Cm tcp_ecn_permitted .
440 If
441 .Cm tcp_ecn_permitted
442 is set to
443 .Sy 0 ,
444 then TCP will not negotiate with a peer that supports ECN mechanism.
445 If
446 .Cm tcp_ecn_permitted
447 is set to
448 .Sy 1
449 when initiating a connection, TCP will not tell a peer that it supports
450 .Sy ECN
451 mechanism.
452 However, it will tell a peer that it supports
453 .Sy ECN
454 mechanism when accepting a new incoming connection request if the peer
455 indicates that it supports
456 .Sy ECN
457 mechanism in the
458 .Sy SYN
459 segment.
460 If
461 .Cm tcp_ecn_permitted
462 is set to 2, in addition to negotiating with a peer on
463 .Sy ECN
464 mechanism when accepting connections, TCP will indicate in the outgoing
465 .Sy SYN
466 segment that it supports
467 .Sy ECN
468 mechanism when TCP makes active outgoing connections.
469 The default for
470 .Cm tcp_ecn_permitted
471 is 1.
472 .El
473 .Pp
474 Turn on the timestamp option in the following way:
475 .Bl -bullet -offset indent -width 4m
476 .It
477 Use
478 .Nm ndd
479 to modify the configuration parameter
480 .Cm tcp_tstamp_always .
481 If
482 .Cm tcp_tstamp_always
483 is
484 .Sy 1 ,
485 the timestamp option will always be set
486 when connecting to a remote machine.
487 If
488 .Cm tcp_tstamp_always
489 is
490 .Sy 0 ,
491 the timestamp option will not be set when connecting to a remote system.
492 The
493 default for
494 .Cm tcp_tstamp_always
495 is
496 .Sy 0 .
497 .It
498 Regardless of the value of
499 .Cm tcp_tstamp_always ,
500 the timestamp option will
501 always be included in a connect acknowledgement (and all succeeding packets) if
502 the connecting system has used the timestamp option.
503 .El
504 .Pp
505 Use the following procedure to turn on the timestamp option only when the
506 window scale option is in effect:
507 .Bl -bullet -offset indent -width 4m
508 .It
509 Use
510 .Nm ndd
511 to modify the configuration parameter
512 .Cm tcp_tstamp_if_wscale .
513 Setting
514 .Cm tcp_tstamp_if_wscale
515 to
516 .Sy 1
517 will cause the timestamp option
518 to be set when connecting to a remote system, if the window scale option has
519 been set.
520 If
521 .Cm tcp_tstamp_if_wscale
522 is
523 .Sy 0 ,
524 the timestamp option will
525 not be set when connecting to a remote system.
526 The default for
527 .Cm tcp_tstamp_if_wscale
528 is
529 .Sy 1 .
530 .El
531 .Pp
532 Protection Against Wrap Around Sequence Numbers
533 .Po Sy PAWS Pc
534 is always used when the
535 timestamp option is set.
536 .Pp
537 The operating system also supports multiple methods of generating initial sequence numbers.
538 One of these methods is the improved technique suggested in RFC 1948.
539 We
540 .Em HIGHLY
541 recommend that you set sequence number generation parameters as
542 close to boot time as possible.
543 This prevents sequence number problems on
544 connections that use the same connection-ID as ones that used a different
545 sequence number generation.
546 The
547 .Sy svc:/network/initial:default
548 service configures the initial sequence number generation.
549 The service reads the value contained in the configuration file
550 .Pa /etc/default/inetinit
551 to determine which method to use.
552 .Pp
553 The
554 .Pa /etc/default/inetinit
555 file is an unstable interface, and may change in future releases.
556 .Sh EXAMPLES
557 .Ss Example 1: Connecting to a server
558 .Bd -literal
559 $ gcc -std=c99 -Wall -lsocket -o client client.c
560 $ cat client.c
561 #include <sys/socket.h>
562 #include <netinet/in.h>
563 #include <netinet/tcp.h>
564 #include <netdb.h>
565 #include <stdio.h>
566 #include <string.h>
567 #include <unistd.h>
568
569 int
570 main(int argc, char *argv[])
571 {
572 struct addrinfo hints, *gair, *p;
573 int fd, rv, rlen;
574 char buf[1024];
575 int y = 1;
576
577 if (argc != 3) {
578 fprintf(stderr, "%s <host> <port>\\n", argv[0]);
579 return (1);
580 }
581
582 memset(&hints, 0, sizeof (hints));
583 hints.ai_family = PF_UNSPEC;
584 hints.ai_socktype = SOCK_STREAM;
585
586 if ((rv = getaddrinfo(argv[1], argv[2], &hints, &gair)) != 0) {
587 fprintf(stderr, "getaddrinfo() failed: %s\\n",
588 gai_strerror(rv));
589 return (1);
590 }
591
592 for (p = gair; p != NULL; p = p->ai_next) {
593 if ((fd = socket(
594 p->ai_family,
595 p->ai_socktype,
596 p->ai_protocol)) == -1) {
597 perror("socket() failed");
598 continue;
599 }
600
601 if (connect(fd, p->ai_addr, p->ai_addrlen) == -1) {
602 close(fd);
603 perror("connect() failed");
604 continue;
605 }
606
607 break;
608 }
609
610 if (p == NULL) {
611 fprintf(stderr, "failed to connect to server\\n");
612 return (1);
613 }
614
615 freeaddrinfo(gair);
616
617 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &y,
618 sizeof (y)) == -1) {
619 perror("setsockopt(SO_KEEPALIVE) failed");
620 return (1);
621 }
622
623 while ((rlen = read(fd, buf, sizeof (buf))) > 0) {
624 fwrite(buf, rlen, 1, stdout);
625 }
626
627 if (rlen == -1) {
628 perror("read() failed");
629 }
630
631 fflush(stdout);
632
633 if (close(fd) == -1) {
634 perror("close() failed");
635 }
636
637 return (0);
638 }
639 $ ./client 127.0.0.1 8080
640 hello
641 $ ./client ::1 8080
642 hello
643 .Ed
644 .Ss Example 2: Accepting client connections
645 .Bd -literal
646 $ gcc -std=c99 -Wall -lsocket -o server server.c
647 $ cat server.c
648 #include <sys/socket.h>
649 #include <netinet/in.h>
650 #include <netinet/tcp.h>
651 #include <netdb.h>
652 #include <stdio.h>
653 #include <string.h>
654 #include <unistd.h>
655 #include <arpa/inet.h>
656
657 void
658 logmsg(struct sockaddr *s, int bytes)
659 {
660 char dq[INET6_ADDRSTRLEN];
661
662 switch (s->sa_family) {
663 case AF_INET: {
664 struct sockaddr_in *s4 = (struct sockaddr_in *)s;
665 inet_ntop(AF_INET, &s4->sin_addr, dq, sizeof (dq));
666 fprintf(stdout, "sent %d bytes to %s:%d\\n",
667 bytes, dq, ntohs(s4->sin_port));
668 break;
669 }
670 case AF_INET6: {
671 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)s;
672 inet_ntop(AF_INET6, &s6->sin6_addr, dq, sizeof (dq));
673 fprintf(stdout, "sent %d bytes to [%s]:%d\\n",
674 bytes, dq, ntohs(s6->sin6_port));
675 break;
676 }
677 default:
678 fprintf(stdout, "sent %d bytes to unknown client\\n",
679 bytes);
680 break;
681 }
682 }
683
684 int
685 main(int argc, char *argv[])
686 {
687 struct addrinfo hints, *gair, *p;
688 int sfd, cfd;
689 int slen, wlen, rv;
690
691 if (argc != 3) {
692 fprintf(stderr, "%s <port> <message>\\n", argv[0]);
693 return (1);
694 }
695
696 slen = strlen(argv[2]);
697
698 memset(&hints, 0, sizeof (hints));
699 hints.ai_family = PF_UNSPEC;
700 hints.ai_socktype = SOCK_STREAM;
701 hints.ai_flags = AI_PASSIVE;
702
703 if ((rv = getaddrinfo(NULL, argv[1], &hints, &gair)) != 0) {
704 fprintf(stderr, "getaddrinfo() failed: %s\\n",
705 gai_strerror(rv));
706 return (1);
707 }
708
709 for (p = gair; p != NULL; p = p->ai_next) {
710 if ((sfd = socket(
711 p->ai_family,
712 p->ai_socktype,
713 p->ai_protocol)) == -1) {
714 perror("socket() failed");
715 continue;
716 }
717
718 if (bind(sfd, p->ai_addr, p->ai_addrlen) == -1) {
719 close(sfd);
720 perror("bind() failed");
721 continue;
722 }
723
724 break;
725 }
726
727 if (p == NULL) {
728 fprintf(stderr, "server failed to bind()\\n");
729 return (1);
730 }
731
732 freeaddrinfo(gair);
733
734 if (listen(sfd, 1024) != 0) {
735 perror("listen() failed");
736 return (1);
737 }
738
739 fprintf(stdout, "waiting for clients...\\n");
740
741 for (int times = 0; times < 5; times++) {
742 struct sockaddr_storage stor;
743 socklen_t alen = sizeof (stor);
744 struct sockaddr *addr = (struct sockaddr *)&stor;
745
746 if ((cfd = accept(sfd, addr, &alen)) == -1) {
747 perror("accept() failed");
748 continue;
749 }
750
751 wlen = 0;
752
753 do {
754 wlen += write(cfd, argv[2] + wlen, slen - wlen);
755 } while (wlen < slen);
756
757 logmsg(addr, wlen);
758
759 if (close(cfd) == -1) {
760 perror("close(cfd) failed");
761 }
762 }
763
764 if (close(sfd) == -1) {
765 perror("close(sfd) failed");
766 }
767
768 fprintf(stdout, "finished.\\n");
769
770 return (0);
771 }
772 $ ./server 8080 $'hello\\n'
773 waiting for clients...
774 sent 6 bytes to [::ffff:127.0.0.1]:59059
775 sent 6 bytes to [::ffff:127.0.0.1]:47448
776 sent 6 bytes to [::ffff:127.0.0.1]:54949
777 sent 6 bytes to [::ffff:127.0.0.1]:55186
778 sent 6 bytes to [::1]:62256
779 finished.
780 .Ed
781 .Sh DIAGNOSTICS
782 A socket operation may fail if:
783 .Bl -tag -offset indent -width 16m
784 .It Er EISCONN
785 A
786 .Fn connect
787 operation was attempted on a socket on which a
788 .Fn connect
789 operation had already been performed.
790 .It Er ETIMEDOUT
791 A connection was dropped due to excessive retransmissions.
792 .It Er ECONNRESET
793 The remote peer forced the connection to be closed (usually because the remote
794 machine has lost state information about the connection due to a crash).
795 .It Er ECONNREFUSED
796 The remote peer actively refused connection establishment (usually because no
797 process is listening to the port).
798 .It Er EADDRINUSE
799 A
800 .Fn bind
801 operation was attempted on a socket with a network address/port pair that has
802 already been bound to another socket.
803 .It Er EADDRNOTAVAIL
804 A
805 .Fn bind
806 operation was attempted on a socket with a network address for which no network
807 interface exists.
808 .It Er EACCES
809 A
810 .Fn bind
811 operation was attempted with a
812 .Dq reserved
813 port number and the effective user ID of the process was not the privileged user.
814 .It Er ENOBUFS
815 The system ran out of memory for internal data structures.
816 .El
817 .Sh SEE ALSO
818 .Xr svcs 1 ,
819 .Xr ndd 1M ,
820 .Xr svcadm 1M ,
821 .Xr ioctl 2 ,
822 .Xr read 2 ,
823 .Xr write 2 ,
824 .Xr accept 3SOCKET ,
825 .Xr bind 3SOCKET ,
826 .Xr connect 3SOCKET ,
827 .Xr getprotobyname 3SOCKET ,
828 .Xr getsockopt 3SOCKET ,
829 .Xr listen 3SOCKET ,
830 .Xr send 3SOCKET ,
831 .Xr smf 5 ,
832 .Xr inet 7P ,
833 .Xr inet6 7P ,
834 .Xr ip 7P ,
835 .Xr ip6 7P
836 .Rs
837 .%A "K. Ramakrishnan"
838 .%A "S. Floyd"
839 .%A "D. Black"
840 .%T "The Addition of Explicit Congestion Notification (ECN) to IP"
841 .%R "RFC 3168"
842 .%D "September 2001"
843 .Re
844 .Rs
845 .%A "M. Mathias"
846 .%A "J. Mahdavi"
847 .%A "S. Ford"
848 .%A "A. Romanow"
849 .%T "TCP Selective Acknowledgement Options"
850 .%R "RFC 2018"
851 .%D "October 1996"
852 .Re
853 .Rs
854 .%A "S. Bellovin"
855 .%T "Defending Against Sequence Number Attacks"
856 .%R "RFC 1948"
857 .%D "May 1996"
858 .Re
859 .Rs
860 .%A "D. Borman"
861 .%A "B. Braden"
862 .%A "V. Jacobson"
863 .%A "R. Scheffenegger, Ed."
864 .%T "TCP Extensions for High Performance"
865 .%R "RFC 7323"
866 .%D "September 2014"
867 .Re
868 .Rs
869 .%A "Jon Postel"
870 .%T "Transmission Control Protocol - DARPA Internet Program Protocol Specification"
871 .%R "RFC 793"
872 .%C "Network Information Center, SRI International, Menlo Park, CA."
873 .%D "September 1981"
874 .Re
875 .Sh NOTES
876 The
877 .Sy tcp
878 service is managed by the service management facility,
879 .Xr smf 5 ,
880 under the service identifier
881 .Sy svc:/network/initial:default .
882 .Pp
883 Administrative actions on this service, such as enabling, disabling, or
884 requesting restart, can be performed using
885 .Xr svcadm 1M .
886 The service's
887 status can be queried using the
888 .Xr svcs 1
889 command.