1 Some less-widely known details of TCP connections.
3 Properly closing the connection.
5 After this code sequence:
7 sock = socket(AF_INET, SOCK_STREAM, 0);
8 connect(sock, &remote, sizeof(remote));
9 write(sock, buffer, 1000000);
11 a large block of data is only buffered by kernel, it can't be sent all at once.
12 What will happen if we close the socket?
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."
21 IOW: if we just close(sock) now, kernel can reset the TCP connection,
22 discarding some not-yet sent data.
24 What can be done about it?
26 Solution #1: block until sending is done:
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.
33 int l_onoff; /* linger active */
34 int l_linger; /* how many seconds to linger for */
37 linger.l_linger = SOME_NUM;
38 setsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger));
41 Solution #2: tell kernel that you are done sending.
42 This makes kernel send FIN, not RST:
44 shutdown(sock, SHUT_WR);
50 Method #1: manually control whether partial sends are allowed:
52 This prevents partially filled packets being sent:
55 setsockopt(fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
57 and this forces last, partially filled packet (if any) to be sent:
60 setsockopt(fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
62 Method #2: make any write to immediately send data, even if it's partial:
65 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &state, sizeof(state));