RST на клиенте после socketclose на сервере
От: tdiff  
Дата: 11.04.18 14:31
Оценка:
Привет,

Клиент и сервер общаются по простому протоколу:

-- client sends request
send()
send()
shutdown(SHUT_WR) -- starts waiting for a reply
read()
...

-- server accepts conn and reads request
read()
...
send(). -- writes reply
closesocket() --and immediately closes its socket

При этом клиент после closesocket() на сервере периодически получает RST. В моём понимании, это означает, что на сервере в recv queue ещё лежат непрочитанные данные. Но:
1. если перед socketclose() на сервере сделать recv(), то он прочитает 0 байт.
2. проблема проходит, если перед closesocket() на сервере вызвать shutdown(SHUT_BOTH).

Как можно объяснить такое поведение?

Платформа Win 7. SO_linger дефолтный.
Отредактировано 11.04.2018 20:07 tdiff . Предыдущая версия . Еще …
Отредактировано 11.04.2018 14:57 tdiff . Предыдущая версия .
Отредактировано 11.04.2018 14:32 tdiff . Предыдущая версия .
Re: RST на клиенте после socketclose
От: Pzz Россия https://github.com/alexpevzner
Дата: 11.04.18 14:43
Оценка:
Здравствуйте, tdiff, Вы писали:

T>При этом клиент после closesocket() периодически получает RST. В моём понимании, это означает, что на сервере в recv queue ещё лежат непрочитанные данные. Но:


Откуда ты знаешь, что получает клиент после closesocket()?
Re[2]: RST на клиенте после socketclose
От: tdiff  
Дата: 11.04.18 14:49
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Здравствуйте, tdiff, Вы писали:


T>>При этом клиент после closesocket() периодически получает RST. В моём понимании, это означает, что на сервере в recv queue ещё лежат непрочитанные данные. Но:


Pzz>Откуда ты знаешь, что получает клиент после closesocket()?


К сожалению, у меня нет возможности запустить Wireshark, но клиент (написан на c#) выходит из Receive с error = SocketError.ConnectionReset.
Re[3]: RST на клиенте после socketclose
От: Pzz Россия https://github.com/alexpevzner
Дата: 11.04.18 14:54
Оценка:
Здравствуйте, tdiff, Вы писали:

T>К сожалению, у меня нет возможности запустить Wireshark, но клиент (написан на c#) выходит из Receive с error = SocketError.ConnectionReset.


Ты SO_LINGER трогал?
Re[4]: RST на клиенте после socketclose
От: tdiff  
Дата: 11.04.18 14:55
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Здравствуйте, tdiff, Вы писали:


T>>К сожалению, у меня нет возможности запустить Wireshark, но клиент (написан на c#) выходит из Receive с error = SocketError.ConnectionReset.


Pzz>Ты SO_LINGER трогал?


Нет
Re: RST на клиенте после socketclose на сервере
От: reversecode google
Дата: 11.04.18 19:37
Оценка:
reset приходит клиенту ? значит на сервер перед клозе нужно поставит шутдаун вр
Re[2]: RST на клиенте после socketclose на сервере
От: tdiff  
Дата: 11.04.18 19:47
Оценка:
Здравствуйте, reversecode, Вы писали:


R>reset приходит клиенту ? значит на сервер перед клозе нужно поставит шутдаун вр


Я это и делаю, но не понимаю, что происходит. Как shutdown wr защищает от rst?
Re[3]: RST на клиенте после socketclose на сервере
От: reversecode google
Дата: 11.04.18 19:54
Оценка:
у вас очень плохо расписано что вы делаете
про то что вы делаете серверу я не вижу, намеки 1) 2) я так понял относятся к клиенту ?
вообщем
http://cs.ecs.baylor.edu/~donahoo/practical/CSockets/TCPRST.pdf
Re[4]: RST на клиенте после socketclose на сервере
От: reversecode google
Дата: 11.04.18 19:56
Оценка:
Здравствуйте, reversecode, Вы писали:


R>у вас очень плохо расписано что вы делаете

R>про то что вы делаете серверу я не вижу, намеки 1) 2) я так понял относятся к клиенту ?
R>вообщем
R>http://cs.ecs.baylor.edu/~donahoo/practical/CSockets/TCPRST.pdf

http://cs.baylor.edu/~donahoo/practical/CSockets/code/HandleTCPClientRST.c
http://cs.baylor.edu/~donahoo/practical/CSockets/code/TCPEchoServer.c

полностью код что бы понятнее
Re[4]: RST на клиенте после socketclose на сервере
От: tdiff  
Дата: 11.04.18 20:01
Оценка:
Здравствуйте, reversecode, Вы писали:


R>у вас очень плохо расписано что вы делаете

R>про то что вы делаете серверу я не вижу, намеки 1) 2) я так понял относятся к клиенту ?
R>вообщем
R>http://cs.ecs.baylor.edu/~donahoo/practical/CSockets/TCPRST.pdf

А, я понял, что плохо написал (обновил описание). В моей ситуации сокет первым закрывает сервер (вызывает closesocket). В этот момент клиент висит на recv(). Соответственно, rst получает клиент как ошибку из recv.

Намеки 1 и 2 относятся к серверу.

Статью уже видел, но из нее непонятно, почему это работает.
Отредактировано 11.04.2018 20:08 tdiff . Предыдущая версия .
Re[5]: RST на клиенте после socketclose на сервере
От: reversecode google
Дата: 11.04.18 20:08
Оценка:
на сервере есть очередь, иногда
если сделать клозе сокет то оно видя не обработанную очередь отправляет ресет кленту
но если даже имея не обработанную входящую очередь, сделать шут вр
то думаю(надо смотреть тцп дампом)
либо
1) канал финализируется и закрывается у клиента, и ресет который может отправить сервер уже клиент игнорит
либо
2) сервер видя что запись потушили, уже не отправляет ресет из за того что есть не обработанная очередь в сокете
Re[5]: RST на клиенте после socketclose
От: Pzz Россия https://github.com/alexpevzner
Дата: 11.04.18 20:10
Оценка:
Здравствуйте, tdiff, Вы писали:

Pzz>>Ты SO_LINGER трогал?


T>Нет


Очень все это выглядит странно. Если на сервере recv() вернул ноль, значит, все уже вычитано, и больше не ожидается (сервер осознал, что клиент сделал shutdown() на запись).

А сокет ты сам полностью контролируешь, или есть еще какой-то код, который с ним чего-то может сделать?
Re[6]: RST на клиенте после socketclose на сервере
От: reversecode google
Дата: 11.04.18 20:10
Оценка:
логичным выглядит вариант 2), нет смысла пихать ресет если уже был отправлен финишь от шут вр
Re[4]: RST на клиенте после socketclose на сервере
От: Pzz Россия https://github.com/alexpevzner
Дата: 11.04.18 20:11
Оценка:
Здравствуйте, reversecode, Вы писали:

R>у вас очень плохо расписано что вы делаете


Все у него хорошо расписано

R>http://cs.ecs.baylor.edu/~donahoo/practical/CSockets/TCPRST.pdf


У него recv() вернул 0. Значит, все данные уже вычитаны, и закрытие сокета на запись осознанно.
Re[6]: RST на клиенте после socketclose на сервере
От: tdiff  
Дата: 11.04.18 20:16
Оценка:
Здравствуйте, reversecode, Вы писали:


R>на сервере есть очередь, иногда

R>если сделать клозе сокет то оно видя не обработанную очередь отправляет ресет кленту
R>но если даже имея не обработанную входящую очередь, сделать шут вр
R>то думаю(надо смотреть тцп дампом)
R>либо
R>1) канал финализируется и закрывается у клиента, и ресет который может отправить сервер уже клиент игнорит
R>либо
R>2) сервер видя что запись потушили, уже не отправляет ресет из за того что есть не обработанная очередь в сокете

ок, спасибо. Я примерно так предполагал, но нигде не видел доки, подтверждающей это.

У меня осталось непонимание, почему read перед close на сервере возвращает ноль? Т.е. очереди нет. Разве что я мог еще не прочитать EOF, например...
Re[7]: RST на клиенте после socketclose на сервере
От: reversecode google
Дата: 11.04.18 20:27
Оценка:
блочный или нон блок сервер ?
надо смотреть тцп дампом что там,еоф или что то другое

код ошибки при получения нуля надо смотреть, хотя я хз как там в шарпе,
если бы была ошибка всегда был ексепшин ? или надо иногда вручную проверять ?
Re[7]: RST на клиенте после socketclose на сервере
От: Pzz Россия https://github.com/alexpevzner
Дата: 11.04.18 21:33
Оценка:
Здравствуйте, tdiff, Вы писали:

T>У меня осталось непонимание, почему read перед close на сервере возвращает ноль? Т.е. очереди нет. Разве что я мог еще не прочитать EOF, например...


Когда read возвращает 0, это и есть EOF
Re[6]: RST на клиенте после socketclose
От: tdiff  
Дата: 13.04.18 21:10
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Очень все это выглядит странно. Если на сервере recv() вернул ноль, значит, все уже вычитано, и больше не ожидается (сервер осознал, что клиент сделал shutdown() на запись).


Pzz>А сокет ты сам полностью контролируешь, или есть еще какой-то код, который с ним чего-то может сделать?


Полностью сам, если не считать какой-нибудь DLP, но это уже совсем эзотерика
Re[8]: RST на клиенте после socketclose на сервере
От: tdiff  
Дата: 13.04.18 21:16
Оценка:
Здравствуйте, reversecode, Вы писали:


R>блочный или нон блок сервер ?

R>надо смотреть тцп дампом что там,еоф или что то другое

R>код ошибки при получения нуля надо смотреть, хотя я хз как там в шарпе,

R> если бы была ошибка всегда был ексепшин ? или надо иногда вручную проверять ?

У меня клиент на шарпе, сервер на плюсах. Он совсем простенький — создаёт по треду на каждое соединение, все сокеты блокирующиеся. Т.к. вся эта красота работает под виндой, recv = 0 означает конец стрима без ошибки.

TCP dump практически недоступен
Re[9]: RST на клиенте после socketclose на сервере
От: reversecode google
Дата: 13.04.18 21:47
Оценка: +1
ноль рид в блокирующем сокете это закрытие соединения
в неблокирующем надо еще ошибку смотреть

T>TCP dump практически недоступен


мы не в каменном веке
ваершарк коммвью итд куча дамперов под винду насыпано в гугле
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.