Re[3]: Socket успешно прочитал 0 байт :( проблемы
От: vsb Казахстан  
Дата: 19.05.20 13:26
Оценка: 3 (1) +2
Здравствуйте, vvv848165@ya.ru, Вы писали:

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


Про какие именно коды ошибок идёт речь? Возможно ты говоришь о ситуации, когда сокет закрыт ненормальным образом, например connection reset.

Т.е. соединение может быть закрыто нормальным образом, когда та сторона вызывает shutdown, в этом случае приходят одни пакеты (FIN).

Соединение может быть "оборвано", например если на той стороне программа упала и соединение подчищает уже ОС или программа вызвала close без shutdown. В этом случае приходят другие пакеты (RST).

А ещё соединение может просто отвалиться по таймауту, если давно не приходило никаких пакетов с той стороны. Это тоже ошибка.

В общем лучше всего подцепиться wireshark-ом и смотреть на конкретные пакеты и то, как они соотносятся с вызываемыми функциями/возвращаемыми значениями.
Отредактировано 19.05.2020 13:29 vsb . Предыдущая версия . Еще …
Отредактировано 19.05.2020 13:28 vsb . Предыдущая версия .
Re: Socket успешно прочитал 0 байт :( проблемы
От: Aquilaware  
Дата: 21.05.20 07:52
Оценка: :))
Здравствуйте, vvv848165@ya.ru, Вы писали:

VYR>Как в таких случаях быть?


Удивлен, что до сих пор никто не дал правильного ответа.

Чтение TCP сокета может возвращать ноль если:

1) Происходит реакция сетевого стека на фрагментацию пакетов. Фрагментация может возникать с определенными устройствами в определенных конфигурациях сети при определенных нагрузках или сценариях. Обычно, в локальной сети фрагментация возникает редко, и поэтому многие неопытные разработчики даже не догадываются о такой возможности, потому что она редко (или почти) не возникает в тепличных условиях
2) Спонтанное пробуждение примитивов ожидания ОС, вызванное особенностями работы ядра (обычное явление во многих ОС)

Что делать если сокет вернул меньше чем ожидалось?

Продолжать читать до тех пор, пока не наберете нужный обьем информации! Или пока сокет не отвалится с ошибкой.

ПОПРАВКА: как верно подметили коллеги, эти рекомендации слишком общие и напоминают сферического коня в ваккуме.

Поэтому нужно учитывать ОС, на которой работает ваше приложение. Подитожу:

  1. В некоторых встраиваемых системах: чтение сокета может спорадически возвращать ноль в виду перечисленных выше причин, и при этом не означать закрытия сокета или ошибки. Это говорит о неполноценной реализации сетевого стека конкретной ОС
  2. Windows: чтение сокета возвращает ноль только при полном или частичном закрытии сокета. Такой сокет уже считается закрытым на чтение, и все дальнейшие попытки прочитать из него будут всегда моментально возвращать 0. Это не означает ошибку, это означает закрытый сокет.
  3. Unix: чтение сокета возвращает ноль только если система не желает удерживать системный вызов в блокирующем состоянии (EINTR, EGAIN, EWOULDBLOCK) или при полном/частичном закрытии сокета.
Отредактировано 23.05.2020 9:08 Aquilaware . Предыдущая версия . Еще …
Отредактировано 23.05.2020 9:08 Aquilaware . Предыдущая версия .
Re[4]: Socket успешно прочитал 0 байт :( проблемы
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 23.05.20 06:40
Оценка: 6 (1)
Здравствуйте, Aquilaware, Вы писали:

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


N>>Откуда ж вас такого юмориста принесло-то...


A>С полей под названием внедрение и реальность.


A>result=0 и errno=success был замечен при чтении из TCP сокета на некоторых встраиваемых системах, с которыми мне приходилось работать. Стеки там были собраны как говорится из "г..на и палок", иногда даже с "интересными" кусками кода датированными концом 80-x.


Ааа, "некоторые встраиваемые"... ну тогда надо всё-таки с самого начала уточнять, что речь о заведомо кривых реализациях. Думаю, тот, кто возится именно с такой реализацией, вряд ли задал бы тут вопрос, не уточняя обстановку.

Android это всё-таки Linux-based решение, там такого не увидеть.

Хотя ещё вопрос — там случайно SysV флаг O_NDELAY не использовался? С ним можно такое получить. Но ни в BSD ни в Linux его принципиально не переносили.

A>Насчет фрагментации. Её вы таки увидите при чтении из TCP сокета даже на "больших" системах! Но проявляется она не как EINTR, а как возвращаемое значение больше 0, но меньше чем просили.


Спасибо, кэп Хотя, да, напоминать про это надо всегда — каждый второй индус (в общем смысле) будет думать, что если что-то одним send() отправили, то точно так же одним recv() и будет получено. Причём он будет тестировать на раздельных пакетах, и будет говорить "у меня всё работает". Тут спасут только массовые расстрелы.

A>Особенно забавный был случай, когда один из разработчиков написал приемник протокольных пакетов, и ожидал что read для сокета возращает именно столько байт, сколько попросили в аргументе. И если результат был меньше, он то ли выкидывал его, то ли вовсе переоткрывал сокет, думая что передатчик "не окончил полностью передачу".


Во-во.

A>Вот эта ситуация проявляется редко, но связана она именно с фрагментацией.

A> В "тихой" сети, всё работало. Но, стояло другой сотне аппаратов поднятся, как некоторые начинали терять протокольное соединение с серверои. Это было очень очень неприятно отлаживать.

В TCP/IP это _не_ называется фрагментацией. Это следствие упаковки нескольких порций отсылки в один IP пакет. Фрагментацией называется, когда IP пакет режется на отправке или по дороге потому, что на каком-то из линков недостаточный MTU.
Может, вы понимаете явление правильно, но термин неуместный.

A>В итоге смогли повторить ситуацию даже на локальной машине в пределах localhost, просто запустив сотню прогаммных эмуляторов устройств вместе с сервером на одной машине. Зацепились отладчиком и увидели эту каку.


Верю, сам видел похожее но давайте не сбивать с толку терминологией.

A>(Все эти детали касаются TCP. С датаграмами по-другому, я о них не говорю вообще)


ok.
The God is real, unless declared integer.
Re[3]: Socket успешно прочитал 0 байт :( проблемы
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 20.05.20 10:21
Оценка: 3 (1)
Здравствуйте, vvv848165@ya.ru, Вы писали:

vsb>> это означает, что соединение закрыто


VYR>Вот то-то и оно что для этого есть специальные коды ошибок и исключения, а не успешный 0 !


Таки непонятен ваш плач. Я правильно понял, что речь, что на той стороне программа не сама решила завершить передачу по соединению в соответствии со своей штатной логикой, а её вместо этого пришлёпнули, и вам хотелось бы видеть в этом случае другой код, чем 0?

Если да — я согласен, что тут есть проблема. Она есть и в варианте локального пайпа (шелл собрал цепочку типа xx | yy, xx отстрелили — yy получит только EOF), и в сетевом. Увы. Но так как сетевое соединение двустороннее, можно спросить состояние — а можно добавить явную метку конца в протокол. Или как на HTTP сделано: посылайте Content-Length или используйте chunked TE, тогда метка завершения всегда будет явной.
Я бы при проектировании этого интерфейса подумал про такие индикации. Но раз за ~30 лет их активного использования не исправляли — проблема считается не настолько серьёзной.
The God is real, unless declared integer.
Re[5]: Socket успешно прочитал 0 байт :( проблемы
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 20.05.20 10:15
Оценка: 1 (1)
Здравствуйте, vvv848165@ya.ru, Вы писали:

Pzz>>Ну например потому, что кроме нормального закрытия соединения бывают еще всякие аварийные варианты. И их может возникнуть желание отличать.


VYR>а как-нибудь что-нибудь дополнительно можно узнать при получении 0 байт по TCP-IP (ну хоть через какие нибудь Api)?


В таких аварийных вариантах вы получите не 0, а -1, и уточняющий код в errno.
The God is real, unless declared integer.
Re[7]: Socket успешно прочитал 0 байт :( проблемы
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 20.05.20 08:40
Оценка: -1
Здравствуйте, vvv848165@ya.ru, Вы писали:

M>>Не понятно, какой конкретный случай ты собрался определять?


VYR>Дак уже говорили что 0 байт может прийти например из-за Shutdown в одну сторону...


Ну и закрывай себе. Либо отправляй то что хотел напоследок, и опять же закрывай. В чём проблема-то?
Маньяк Робокряк колесит по городу
Re[2]: Socket успешно прочитал 0 байт :( проблемы
От: Aquilaware  
Дата: 21.05.20 07:56
Оценка: :)
Здравствуйте, Слава, Вы писали:

С>Может вы всё-таки будете внимательно читать документацию по сокетам? Там явно сказано всё то, что вам в теме написали. Прямо вот на MSDN, и ещё в паре десятков книжек и примеров по сетевому программированию.


Пардон, но в этой теме написана откровенная чушь.
Re[4]: Socket успешно прочитал 0 байт :( проблемы
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 23.05.20 09:51
Оценка: +1
Здравствуйте, Aquilaware, Вы писали:

A>Несколько десятков.


A>См. EINTR на который Marty указал. Shutdown это только один из случаев, но он не единственный. Нужно errno смотреть. У каждого стека колокольчики со свистками.


При EINTR возвращается не ноль
Маньяк Робокряк колесит по городу
Socket успешно прочитал 0 байт :( проблемы
От: vvv848165@ya.ru  
Дата: 19.05.20 12:56
Оценка:
Эту проблему я наблюдал и на С++ и на С# и на java ...
Причем успешно прочитать 0 байт можно как минимум по 2 причинам
1) Есть сокетные соединения с программой Android OC при бездействии экрана на противоположенном конце может прийти несколько пустых пакетов (может баг???)
2) Если одну из программ придушить диспетчером задач, то на противоположенном конце часто периодически сыплются такие пустые приёмы и грузят процессор довольно долго(покудо вдруг Win не сообразит выдать ошибку)

Как в таких случаях быть?

Что можно придумать кроме отсылки NOOP с таймаутом?

на MSDN видел кусок кода когда просто закрывают (не уточняя причину) — как-то не по русски
https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.socket.endreceive?view=netcore-3.1 https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.socket.endreceive?view=netcore-3.1
Re: Socket успешно прочитал 0 байт :( проблемы
От: vsb Казахстан  
Дата: 19.05.20 13:03
Оценка:
man read

On success, the number of bytes read is returned (zero indicates end of file)

В случае сокета это означает, что соединение закрыто. Непонятно, в чём тут проблема? Прочитал 0, закрыл соединение со своей стороны и всё.
Отредактировано 19.05.2020 13:04 vsb . Предыдущая версия .
Re[2]: Socket успешно прочитал 0 байт :( проблемы
От: vvv848165@ya.ru  
Дата: 19.05.20 13:16
Оценка:
Здравствуйте, vsb, Вы писали:

vsb> это означает, что соединение закрыто


Вот то-то и оно что для этого есть специальные коды ошибок и исключения, а не успешный 0 !
Re[2]: Socket успешно прочитал 0 байт :( проблемы
От: vvv848165@ya.ru  
Дата: 19.05.20 13:20
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>man read


vsb>On success, the number of bytes read is returned (zero indicates end of file)


vsb>В случае сокета это означает, что соединение закрыто. Непонятно, в чём тут проблема? Прочитал 0, закрыл соединение со своей стороны и всё.


кстати ты прав но почему для закрытых сокетов есть отдельные коды ошибок?
Re[4]: Socket успешно прочитал 0 байт :( проблемы
От: vvv848165@ya.ru  
Дата: 19.05.20 13:40
Оценка:
Здравствуйте, vsb


Ты прав! но как определить конкретный случай ? чтобы не закрыть случайно не совсем безнадёжное соединение из-за одного нулевого ?

vsb>А ещё соединение может просто отвалиться по таймауту, если давно не приходило никаких пакетов с той стороны.

вроде почти день тестил соединения Win — Win или и Android — Android по таймауту так просто не обрывались
а вот Win — Android или любой *nix — Android жди кучу бед (одно из них пустые пакеты)
Re: Socket успешно прочитал 0 байт :( проблемы
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 19.05.20 15:10
Оценка:
Здравствуйте, vvv848165@ya.ru, Вы писали:

VYR>Эту проблему я наблюдал и на С++ и на С# и на java ...


Тип транспорта? TCP, UDP, SCTP, другое?

На TCP это означает, что та сторона закрылась — можно дальше читать до посинения, будет только ответ 0.
На UDP — пустая датаграмма (законная штука).

UPDATE: везде подразумеваю, что длина буфера в read(), recv(), аналогах — больше 0.
Если она 0, то 0 и возвращается, но это не существенный случай.
The God is real, unless declared integer.
Отредактировано 27.05.2020 4:50 netch80 . Предыдущая версия .
Re: Socket успешно прочитал 0 байт :( проблемы
От: Pzz Россия https://github.com/alexpevzner
Дата: 19.05.20 17:40
Оценка:
Здравствуйте, vvv848165@ya.ru, Вы писали:

VYR>Эту проблему я наблюдал и на С++ и на С# и на java ...

VYR>Причем успешно прочитать 0 байт можно как минимум по 2 причинам

Для TCP прочтение 0 байт — надежный признак того, что соединение закрыли с другой стороны. В случае UDP реально можно получить пустой пакет (пакет, содержащий 0 байтов данных). Но зато у UDP не бывает закрытия соединения с другой стороны.
Re[3]: Socket успешно прочитал 0 байт :( проблемы
От: Pzz Россия https://github.com/alexpevzner
Дата: 19.05.20 17:42
Оценка:
Здравствуйте, vvv848165@ya.ru, Вы писали:

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


Ну например потому, что кроме нормального закрытия соединения бывают еще всякие аварийные варианты. И их может возникнуть желание отличать.
Re[2]: Socket успешно прочитал 0 байт :( проблемы
От: Pzz Россия https://github.com/alexpevzner
Дата: 19.05.20 17:42
Оценка:
Здравствуйте, netch80, Вы писали:

N>На TCP это означает, что та сторона закрылась — можно дальше читать до посинения, будет только ответ 0.

N>На UDP — пустая датаграмма (законная штука).

А для SCTP?
Re[3]: Socket успешно прочитал 0 байт :( проблемы
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 19.05.20 18:09
Оценка:
Здравствуйте, Pzz, Вы писали:

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


N>>На TCP это означает, что та сторона закрылась — можно дальше читать до посинения, будет только ответ 0.

N>>На UDP — пустая датаграмма (законная штука).

Pzz>А для SCTP?


Отправка пустого сообщения получает отказ EINVAL — по крайней мере под Linux и BSD.
Поэтому чтение аналогично TCP — пришла длина 0, значит, закрыли с той стороны.
The God is real, unless declared integer.
Re[5]: Socket успешно прочитал 0 байт :( проблемы
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 19.05.20 18:16
Оценка:
Здравствуйте, vvv848165@ya.ru, Вы писали:


VYR>Ты прав! но как определить конкретный случай ?


Не понятно, какой конкретный случай ты собрался определять?


VYR>чтобы не закрыть случайно не совсем безнадёжное соединение из-за одного нулевого ?


А вот это совсем не понял
Маньяк Робокряк колесит по городу
Re[6]: Socket успешно прочитал 0 байт :( проблемы
От: vvv848165@ya.ru  
Дата: 20.05.20 05:57
Оценка:
Здравствуйте, Marty, Вы писали:

M>Не понятно, какой конкретный случай ты собрался определять?


Дак уже говорили что 0 байт может прийти например из-за Shutdown в одну сторону...

На выходных надеюсь другой телефон протестировать (может такие баги только у моего Xiamoni)
Re[4]: Socket успешно прочитал 0 байт :( проблемы
От: vvv848165@ya.ru  
Дата: 20.05.20 06:00
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Ну например потому, что кроме нормального закрытия соединения бывают еще всякие аварийные варианты. И их может возникнуть желание отличать.


а как-нибудь что-нибудь дополнительно можно узнать при получении 0 байт по TCP-IP (ну хоть через какие нибудь Api)?
Re: Socket успешно прочитал 0 байт :( проблемы
От: Слава  
Дата: 20.05.20 09:51
Оценка:
Здравствуйте, vvv848165@ya.ru, Вы писали:

VYR>Эту проблему я наблюдал и на С++ и на С# и на java ...


Может вы всё-таки будете внимательно читать документацию по сокетам? Там явно сказано всё то, что вам в теме написали. Прямо вот на MSDN, и ещё в паре десятков книжек и примеров по сетевому программированию.
Re[4]: Socket успешно прочитал 0 байт :( проблемы
От: vsb Казахстан  
Дата: 20.05.20 14:10
Оценка:
Здравствуйте, netch80, Вы писали:

N>Таки непонятен ваш плач. Я правильно понял, что речь, что на той стороне программа не сама решила завершить передачу по соединению в соответствии со своей штатной логикой, а её вместо этого пришлёпнули, и вам хотелось бы видеть в этом случае другой код, чем 0?


Разве в таком случае будет 0? Вроде должен прийти пакет RST и будет -1 с econnreset.
Re[5]: Socket успешно прочитал 0 байт :( проблемы
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 20.05.20 16:14
Оценка:
Здравствуйте, vsb, Вы писали:

N>>Таки непонятен ваш плач. Я правильно понял, что речь, что на той стороне программа не сама решила завершить передачу по соединению в соответствии со своей штатной логикой, а её вместо этого пришлёпнули, и вам хотелось бы видеть в этом случае другой код, чем 0?


vsb>Разве в таком случае будет 0? Вроде должен прийти пакет RST и будет -1 с econnreset.


Проверьте у себя, не вопрос.
Я вижу, что Linux и FreeBSD — возвращают 0.
The God is real, unless declared integer.
Re[2]: Socket успешно прочитал 0 байт :( проблемы
От: reversecode google
Дата: 20.05.20 20:13
Оценка:
вы не понимаете современную молодежь
зачем читать и разбираться ?
достаточно прийти на ктыв, закидать пацанов вопросами, пусть разбираются, объясняют, дают правильные советы
Re[2]: Socket успешно прочитал 0 байт :( проблемы
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 21.05.20 07:55
Оценка:
Здравствуйте, Aquilaware, Вы писали:

A> 2) Спонтанное пробуждение примитивов ожидания ОС, вызванное особенностями работы ядра (обычное явление во многих ОС)



Емнип там ошибка будет
Маньяк Робокряк колесит по городу
Re[3]: Socket успешно прочитал 0 байт :( проблемы
От: Aquilaware  
Дата: 21.05.20 07:59
Оценка:
Здравствуйте, Marty, Вы писали:

M>Емнип там ошибка будет


Неа. 0 это не ошибка. Это значит — попробуй еще, пока что не набралось. Касается только сокетов.

Для файлов на файловой системе 0 возвращается когда достигнут конец файла.
Re[4]: Socket успешно прочитал 0 байт :( проблемы
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 21.05.20 08:04
Оценка:
Здравствуйте, Aquilaware, Вы писали:

M>>Емнип там ошибка будет


A>Неа. 0 это не ошибка. Это значит — попробуй еще, пока что не набралось. Касается только сокетов.


A>Для файлов на файловой системе 0 возвращается когда достигнут конец файла.


Не. Должна вернуть ошибку, а errno будет EINTR
Маньяк Робокряк колесит по городу
Re[2]: Socket успешно прочитал 0 байт :( проблемы
От: reversecode google
Дата: 21.05.20 08:37
Оценка:
Здравствуйте, Aquilaware, Вы писали:

A>Здравствуйте, vvv848165@ya.ru, Вы писали:


VYR>>Как в таких случаях быть?


A>Удивлен, что до сих пор никто не дал правильного ответа.


да что вы говорите ?
http://man7.org/linux/man-pages/man2/recv.2.html

When a stream socket peer has performed an orderly shutdown, the
return value will be 0 (the traditional "end-of-file" return).

и сколько мисье написал сетевых программ за свою жизнь?
Re[5]: Socket успешно прочитал 0 байт :( проблемы
От: Aquilaware  
Дата: 21.05.20 08:44
Оценка:
Здравствуйте, Marty, Вы писали:

M>Не. Должна вернуть ошибку, а errno будет EINTR


Как-то так, но EINTR это даже не ошибка, а призыв повторить системный вызов, потому что он был прерван по какой-либо причине:

Many system calls will report the EINTR error code if a signal occurred while the system call was in progress. No error actually occurred, it's just reported that way because the system isn't able to resume the system call automatically.

здесь

В случае Unix, одной из причин может стать сигнал. Но я видел достаточно встраиваемых сетевых стеков, там где никаких сигналов даже нет, но поведение операции чтения из TCP сокета такое же, естественно без EINTR, а просто 0 в результате. Следующие попытки чтения успешны, сокет не разрывается, просто вот в силу причин иногда проскакивает 0. Windows — то же самое.
Re[6]: Socket успешно прочитал 0 байт :( проблемы
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 21.05.20 08:50
Оценка:
Здравствуйте, Aquilaware, Вы писали:

M>>Не. Должна вернуть ошибку, а errno будет EINTR


A>Как-то так, но EINTR это даже не ошибка, а призыв повторить системный вызов, потому что он был прерван по какой-либо причине:


Ну, код ошибки анализировать таки надо, да. А то еще бывают всякие EWOULDBLOCK etc.
Главное, что read не 0 возвращает


A>В случае Unix, одной из причин может стать сигнал. Но я видел достаточно встраиваемых сетевых стеков, там где никаких сигналов даже нет, но поведение операции чтения из TCP сокета такое же, естественно без EINTR, а просто 0 в результате. Следующие попытки чтения успешны, сокет не разрывается, просто вот в силу причин иногда проскакивает 0.


Ну, это кривые реализации, что тут поделать. Надо курить доки/сорцы конкретного стека, и тюнить под него. Но так не должно быть

A>Windows — то же самое.


Никогда такого не видел под виндой
Маньяк Робокряк колесит по городу
Re[3]: Socket успешно прочитал 0 байт :( проблемы
От: Aquilaware  
Дата: 21.05.20 08:52
Оценка:
Здравствуйте, reversecode, Вы писали:

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


A>>Здравствуйте, vvv848165@ya.ru, Вы писали:


VYR>>>Как в таких случаях быть?


A>>Удивлен, что до сих пор никто не дал правильного ответа.


R>да что вы говорите ?

R>http://man7.org/linux/man-pages/man2/recv.2.html
R>

R> When a stream socket peer has performed an orderly shutdown, the
R> return value will be 0 (the traditional "end-of-file" return).

R>и сколько мисье написал сетевых программ за свою жизнь?

Несколько десятков.

См. EINTR на который Marty указал. Shutdown это только один из случаев, но он не единственный. Нужно errno смотреть. У каждого стека колокольчики со свистками.

Собственно, автор топика не акцентировал внимание на конкретной ОС. Если есть конкретика, то нужно маны покурить. А если вобщем почему сокет возвращает 0 и errno = EINTR или вообще success, то ответ мисье надеюсь предоставил достаточно исчерпывающей.

Пардоньте за конфуз.
Re[7]: Socket успешно прочитал 0 байт :( проблемы
От: Aquilaware  
Дата: 21.05.20 09:05
Оценка:
Здравствуйте, Marty, Вы писали:

M>Никогда такого не видел под виндой


Да, винду я мог по инерции приплести. Там это скорее всего означает то же что и в Unix минус сигналы: сокет закрыт на чтение и читать из него более нельзя.
Re[2]: Socket успешно прочитал 0 байт :( проблемы
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 21.05.20 15:36
Оценка:
Здравствуйте, Aquilaware, Вы писали:

A>Удивлен, что до сих пор никто не дал правильного ответа.


Да, настолько неправильных ответов тут ещё не давали — и это хорошо.

A>Чтение сокета может возвращать ноль если:

A> 1) Происходит реакция сетевого стека на фрагментацию пакетов. Фрагментация может возникать с определенными устройствами в определенных конфигурациях сети при определенных нагрузках или сценариях. Обычно, в локальной сети фрагментация возникает редко, и поэтому многие неопытные разработчики даже не догадываются о такой возможности, потому что она редко (или почти) не возникает в тепличных условиях

Если вы не читаете каким-нибудь tcpdump, вы не увидите фрагмент пакета. Вообще.

A> 2) Спонтанное пробуждение примитивов ожидания ОС, вызванное особенностями работы ядра (обычное явление во многих ОС)


Если речь про сигналы, будет -1 и EINTR.
В некоторых особых условиях можно получить -1 и EAGAIN.
В особо некоторых — EWOULDBLOCK, который отличается от EAGAIN (там, где отличается)

Если включено nonblocking, получено -1 и EAGAIN — это штатно.

A>Что делать если сокет вернул 0 или меньше чем ожидалось?


A>Продолжать читать до тех пор, пока не наберете нужный обьем информации! Или пока сокет не отвалится с ошибкой.


Особенно "ценный" совет для SOCK_DGRAM или SOCK_SEQPACKET.

Откуда ж вас такого юмориста принесло-то...
The God is real, unless declared integer.
Re[3]: Socket успешно прочитал 0 байт :( проблемы
От: Aquilaware  
Дата: 22.05.20 21:36
Оценка:
Здравствуйте, netch80, Вы писали:

N>Откуда ж вас такого юмориста принесло-то...


С полей под названием внедрение и реальность.

result=0 и errno=success был замечен при чтении из TCP сокета на некоторых встраиваемых системах, с которыми мне приходилось работать. Стеки там были собраны как говорится из "г..на и палок", иногда даже с "интересными" кусками кода датированными концом 80-x.

Насчет фрагментации. Её вы таки увидите при чтении из TCP сокета даже на "больших" системах! Но проявляется она не как EINTR, а как возвращаемое значение больше 0, но меньше чем просили.

Особенно забавный был случай, когда один из разработчиков написал приемник протокольных пакетов, и ожидал что read для сокета возращает именно столько байт, сколько попросили в аргументе. И если результат был меньше, он то ли выкидывал его, то ли вовсе переоткрывал сокет, думая что передатчик "не окончил полностью передачу".

Вот эта ситуация проявляется редко, но связана она именно с фрагментацией. В "тихой" сети, всё работало. Но, стояло другой сотне аппаратов поднятся, как некоторые начинали терять протокольное соединение с серверои. Это было очень очень неприятно отлаживать.

В итоге смогли повторить ситуацию даже на локальной машине в пределах localhost, просто запустив сотню прогаммных эмуляторов устройств вместе с сервером на одной машине. Зацепились отладчиком и увидели эту каку.

(Все эти детали касаются TCP. С датаграмами по-другому, я о них не говорю вообще)
Re[5]: Socket успешно прочитал 0 байт :( проблемы
От: Aquilaware  
Дата: 23.05.20 08:37
Оценка:
Здравствуйте, netch80, Вы писали:

N>В TCP/IP это _не_ называется фрагментацией. Это следствие упаковки нескольких порций отсылки в один IP пакет. Фрагментацией называется, когда IP пакет режется на отправке или по дороге потому, что на каком-то из линков недостаточный MTU.

N>Может, вы понимаете явление правильно, но термин неуместный.

Вы правы. Спасибо за уточнение.
Re: Socket успешно прочитал 0 байт :( проблемы
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 24.05.20 16:52
Оценка:
Здравствуйте, vvv848165@ya.ru, Вы писали:

VYR>Эту проблему я наблюдал и на С++ и на С# и на java ...

VYR>Причем успешно прочитать 0 байт можно как минимум по 2 причинам
VYR>1) Есть сокетные соединения с программой Android OC при бездействии экрана на противоположенном конце может прийти несколько пустых пакетов (может баг???)
VYR>2) Если одну из программ придушить диспетчером задач, то на противоположенном конце часто периодически сыплются такие пустые приёмы и грузят процессор довольно долго(покудо вдруг Win не сообразит выдать ошибку)

Я тут мимо проходил...

Клиент и сервер на одном компьютере (Win10).

У меня никто никого не придушивал.

В нагрузочном тесте на клиенте вылезла такая ошибка:

[winsock][BUG CHECK] Чтение из закрытого порта подключения. Ошибка WinSock: 0.


  Код чтения из порта
size_t RemoteFB__INET_Socket::Helper__Socket_Recv(size_t const cb,
                                                  void*  const pv)
{
 assert(cb>0);
 assert(pv!=nullptr);

 CHECK_WRITE_PTR(pv,cb);

 const int icb=structure::can_numeric_cast<int>(cb)
                 ?static_cast<int>(cb)
                 :structure::t_numeric_limits<int>::max_value();

 assert(icb>0);
 assert(size_t(icb)<=cb);

 const int n=m_spProvider->m_recv.point()
              (m_hSocket,
               reinterpret_cast<char*>(pv),
               icb,
               RemoteFB__INET_StaticCfg::c_FB_RECV_FLAGS);

 if(n==SOCKET_ERROR)
 {
  const int winsockErr=m_spProvider->m_WSAGetLastError.point()();

  //! \todo
  //!  Process interupt error?

  // ERROR - failed to read from INET port
  t_ibp_error exc(E_FAIL,
                  ibp_mce_winsock__failed_to_read_from_port_1,
                  IBP_CreateCustomErrorFor_CnFailed());

  exc<<winsockErr;

  exc.raise_me();
 }//if n==SOCKET_ERROR

 if(n==0) //<----------------------- ВОТ ЗДЕСЬ ПРИЕЗЖАЕТ НОЛЬ И ВЫКИДЫВАЕТСЯ ОШИБКА.
 {
  const int winsockErr=m_spProvider->m_WSAGetLastError.point()();

  // ERROR - [BUG CHECK] read from closed socket?

  t_ibp_error exc(E_FAIL,
                  ibp_mce_winsock__bug_check__read_from_closed_port_1,
                  IBP_CreateCustomErrorFor_CnFailed());

  exc<<winsockErr;

  exc.raise_me();
 }//if

 if(n<0)
 {
  // ERROR - unexpected result value from recv

  const int winsockErr=m_spProvider->m_WSAGetLastError.point()();

  t_ibp_error exc(E_FAIL,
                  ibp_mce_winsock__bug_check__unexpected_result_code_from_recv_operation_2,
                  IBP_CreateCustomErrorFor_CnFailed());

  exc<<n<<winsockErr;

  exc.raise_me();
 }//if n<0

 if(n>icb)
 {
  // ERROR - [BUG CHECK] read incorrect number of bytes

  t_ibp_error exc(E_FAIL,
                  ibp_mce_winsock__bug_check__recv_read_more_than_expected_2,
                  IBP_CreateCustomErrorFor_CnFailed());

  exc<<n<<icb;

  exc.raise_me();
 }//if

 return static_cast<size_t>(n);
}//Helper__Socket_Recv


Сам сервер не упал.

Что там произошло —

Такая херня начала происходить относительно недавно (впервые — может месяц, два назад). Сейчас вот второй раз вижу.

Windows последний раз обновлялась в прошлом году.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.