Re[2]: Socket успешно прочитал 0 байт :( проблемы
От: reversecode google
Дата: 20.05.20 20:13
Оценка:
вы не понимаете современную молодежь
зачем читать и разбираться ?
достаточно прийти на ктыв, закидать пацанов вопросами, пусть разбираются, объясняют, дают правильные советы
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[2]: Socket успешно прочитал 0 байт :( проблемы
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 21.05.20 07:55
Оценка:
Здравствуйте, Aquilaware, Вы писали:

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



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

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


Пардон, но в этой теме написана откровенная чушь.
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[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[5]: Socket успешно прочитал 0 байт :( проблемы
От: Aquilaware  
Дата: 23.05.20 08:37
Оценка:
Здравствуйте, netch80, Вы писали:

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

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

Вы правы. Спасибо за уточнение.
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 возвращается не ноль
Маньяк Робокряк колесит по городу
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...
Пока на собственное сообщение не было ответов, его можно удалить.