diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2013-09-17 16:24:01 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2013-09-17 16:24:01 +0200 |
commit | d7ea34ee710fe97fc57235dce165fcc5f50a512a (patch) | |
tree | 4d6aea04b91c2bd984bc18aae52ad09aedb71756 | |
parent | 32ed30d96b56ea7322218061f09e62feda9948e3 (diff) | |
download | busybox-w32-d7ea34ee710fe97fc57235dce165fcc5f50a512a.tar.gz busybox-w32-d7ea34ee710fe97fc57235dce165fcc5f50a512a.tar.bz2 busybox-w32-d7ea34ee710fe97fc57235dce165fcc5f50a512a.zip |
Documentation update
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | docs/tcp.txt | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/docs/tcp.txt b/docs/tcp.txt index 766766387..2000f3110 100644 --- a/docs/tcp.txt +++ b/docs/tcp.txt | |||
@@ -18,8 +18,11 @@ What will happen if we close the socket? | |||
18 | received after close() is called, its TCP SHOULD send a RST | 18 | received after close() is called, its TCP SHOULD send a RST |
19 | to show that data was lost." | 19 | to show that data was lost." |
20 | 20 | ||
21 | IOW: if we just close(sock) now, kernel can reset the TCP connection, | 21 | IOW: if we just close(sock) now, kernel can reset the TCP connection |
22 | discarding some not-yet sent data. | 22 | (send RST packet). |
23 | |||
24 | This is problematic for two reasons: it discards some not-yet sent | ||
25 | data, and it may be reported as error, not EOF, on peer's side. | ||
23 | 26 | ||
24 | What can be done about it? | 27 | What can be done about it? |
25 | 28 | ||
@@ -46,14 +49,14 @@ This makes kernel send FIN after all data is written: | |||
46 | 49 | ||
47 | However, experiments on Linux 3.9.4 show that kernel can return from | 50 | However, experiments on Linux 3.9.4 show that kernel can return from |
48 | shutdown() and from close() before all data is sent, | 51 | shutdown() and from close() before all data is sent, |
49 | and if peer sends any data to us after this, kernel stll responds with | 52 | and if peer sends any data to us after this, kernel still responds with |
50 | RST before all our data is sent. | 53 | RST before all our data is sent. |
51 | 54 | ||
52 | In practice the protocol in use often does not allow peer to send | 55 | In practice the protocol in use often does not allow peer to send |
53 | such data to us, in which case this solution is acceptable. | 56 | such data to us, in which case this solution is acceptable. |
54 | 57 | ||
55 | If you know that peer is going to close its end after it sees our FIN | 58 | Solution #3: if you know that peer is going to close its end after it sees |
56 | (as EOF), it might be a good idea to perform a read after shutdown(). | 59 | our FIN (as EOF), it might be a good idea to perform a read after shutdown(). |
57 | When read finishes with 0-sized result, we conclude that peer received all | 60 | When read finishes with 0-sized result, we conclude that peer received all |
58 | the data, saw EOF, and closed its end. | 61 | the data, saw EOF, and closed its end. |
59 | 62 | ||
@@ -61,6 +64,14 @@ However, this incurs small performance penalty (we run for a longer time) | |||
61 | and requires safeguards (nonblocking reads, timeouts etc) against | 64 | and requires safeguards (nonblocking reads, timeouts etc) against |
62 | malicious peers which don't close the connection. | 65 | malicious peers which don't close the connection. |
63 | 66 | ||
67 | Solutions #1 and #2 can be combined: | ||
68 | |||
69 | /* ...set up struct linger... then: */ | ||
70 | setsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)); | ||
71 | shutdown(sock, SHUT_WR); | ||
72 | /* At this point, kernel sent FIN packet, not RST, to the peer, */ | ||
73 | /* even if there is buffered read data from the peer. */ | ||
74 | close(sock); | ||
64 | 75 | ||
65 | Defeating Nagle. | 76 | Defeating Nagle. |
66 | 77 | ||