Socket: как connect / accept использует трехстороннее рукопожатие, если они вообще используются? - PullRequest
0 голосов
/ 19 июня 2020

У меня есть TCP-сервер и несколько клиентов пытаются подключиться к этому серверу почти одновременно. Я заметил, что:

  1. На стороне клиента connect может возвращать 0, даже если трехстороннее рукопожатие еще не завершено.

  2. На стороне сервера accept может не возвращаться даже после завершения трехстороннего рукопожатия.

Чтобы проиллюстрировать обе точки, вот трассировки Wireshark (сервер прослушивает на порт 1234):

1. Вот трассировки Wireshark для случая, когда клиент connect возвращает 0, даже если трехстороннее рукопожатие не было завершено (отсутствует последний SYN от клиента):

// calls ::connect ...
59507 → 1234 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 WS=256 SACK_PERM=1
1234 → 59507 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1460 WS=256 SACK_PERM=1
// ... and ::connect returned 0, despite the above 2 lines 
// forming an incomplete handshake. Why?

// after the ::connect, client calls ::send to send 8 bytes ...
59507 → 1234 [PSH, ACK] Seq=1 Ack=1 Win=262656 Len=8

// ... but we got reset by peer
1234 → 59507 [RST] Seq=1 Win=0 Len=0

// ... and as expected, ::send returned 10054 (WSAECONNRESET)

2 . Серверное accept не возвращается даже после завершения трехстороннего рукопожатия:

// server calls ::accept ...
59643 → 1234 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 WS=256 SACK_PERM=1
1234 → 59643 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1460 WS=256 SACK_PERM=1
59643 → 1234 [ACK] Seq=1 Ack=1 Win=262656 Len=0
// At this point, we have a complete handshake, but server's ::accept doesn't return. Why?

// In the next line, server sends a RST. This doesn't cause the server's ::accept call 
// to return an INVALID_SOCKET, which doesn't seem unreasonable (since nothing is accepted), 
// nor is this the point of the question, but I am including the RST trace here 
// for completeness. The main point is that it's as if server's ::accept is oblivious 
// to the successful handshake.
1234 → 59643 [RST] Seq=1 Win=0 Len=0

Вопросы:

  1. Когда именно возвращается connect? Очевидно, приведенные выше трассировки предполагают, что connect может вернуть (и объявить успех с возвращаемым значением 0), даже если рукопожатие не завершено.

  2. Когда именно возвращается accept? Следы выше говорят о том, что завершение трехстороннего рукопожатия недостаточно для возврата accept, что вызывает недоумение.

Итак, это как если бы connect не Не заботится о проверке рукопожатия, в то время как accept настолько строг, что успешного рукопожатия недостаточно для его возврата?

1 Ответ

2 голосов
/ 20 июня 2020

Итак, чтобы ответить на вопрос,

  • Когда возвращаются connect() и accept()?

enter image description here

I am quoting from the source "Unix Network Programming" -- By W. Richard Stevens. The connect() returns after the first two steps of the handshake. While the accept() returns when an entry is placed in the completed queue. The meaning of queues are given as:

When the client requests a TCP connection, the server's TCP stack creates an entry in the incomplete queue, then the 3-way TCP handshake is managed by the server TCP stack. The connection is moved from the incomplete queue to the completed queue when the last message of the TCP handshake arrives (ACK or PiggyBacked ACK).

For other questions raised in the comments:

  • How does the backlog (2nd parameter of the listen()) affect the queue size?

backlog is not equal to the queue size, the queue size set by the backlog varies from system to system. Below table lists the backlog and corresponding queue values for some systems:

введите описание изображения здесь

  • Что делает сервер, когда он получает SYN, а очередь заполнена?

Если очереди заполнены, когда приходит клиент SYN, TCP игнорирует приходящий SYN (стр. 930-931 0f TCPv2); он не отправляет RST. Поскольку состояние считается временным, и клиент может повторить попытку через некоторое время, надеясь найти место в очереди. Если вместо этого отправляется RST, то неясно, заполнены ли очереди сервера или сервер не прослушивает этот порт.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...