blob: 7951e1c8bedc2c4bfce020502b5b73162c1e6623 [file] [log] [blame]
Denys Vlasenko78011482013-07-25 14:00:37 +02001 Some less-widely known details of TCP connections.
2
3 Properly closing the connection.
4
5After this code sequence:
6
7 sock = socket(AF_INET, SOCK_STREAM, 0);
8 connect(sock, &remote, sizeof(remote));
9 write(sock, buffer, 1000000);
10
11a large block of data is only buffered by kernel, it can't be sent all at once.
12What will happen if we close the socket?
13
14"A host MAY implement a 'half-duplex' TCP close sequence, so that
15 an application that has called close() cannot continue to read
16 data from the connection. If such a host issues a close() call
17 while received data is still pending in TCP, or if new data is
18 received after close() is called, its TCP SHOULD send a RST
19 to show that data was lost."
20
21IOW: if we just close(sock) now, kernel can reset the TCP connection,
22discarding some not-yet sent data.
23
24What can be done about it?
25
26Solution #1: block until sending is done:
27
28 /* When enabled, a close(2) or shutdown(2) will not return until
29 * all queued messages for the socket have been successfully sent
30 * or the linger timeout has been reached.
31 */
32 struct linger {
33 int l_onoff; /* linger active */
34 int l_linger; /* how many seconds to linger for */
35 } linger;
36 linger.l_onoff = 1;
37 linger.l_linger = SOME_NUM;
38 setsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger));
39 close(sock);
40
41Solution #2: tell kernel that you are done sending.
42This makes kernel send FIN, not RST:
43
44 shutdown(sock, SHUT_WR);
45 close(sock);
46
47
48 Defeating Nagle.
49
50Method #1: manually control whether partial sends are allowed:
51
52This prevents partially filled packets being sent:
53
54 int state = 1;
55 setsockopt(fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
56
57and this forces last, partially filled packet (if any) to be sent:
58
59 int state = 0;
60 setsockopt(fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
61
62Method #2: make any write to immediately send data, even if it's partial:
63
64 int state = 1;
65 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &state, sizeof(state));