| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Сети > send возвращает ошибку, но код ошибки 0 |
| Автор: Alexeis 27.9.2011, 12:58 | ||
Соединение активно, TCP/IP клиентский сокет в режиме блокировки. Передает блоки по 4кб. После передачи ~20кб данных функция send неожиданно выдает результат -1, т.е. SOCKET_ERROR, но когда смотрим WSAGetLastError() , то код ошибки 0, т.е. успех
Опытным путем было установлено, что если слать данные серверу реже, то ошибка не возникает. Отсюда возникло предположение о том, что переполняется либо буфер отправки клиента, либо буфер приема сервера, но в этом случае WSAGetLastError не должен возвращать успех. Вообще, если не вызывать WSASetLastError(0); то код ошибки получается от вызова другой функции, т.е. функция send вообще не устанавливает код ошибки, так как будто ошибка и не происходила вовсе (так описано в документации по send). Все таки ошибка была или нет? А если была, то как узнать ее описание? |
| Автор: Alexeis 27.9.2011, 16:07 | ||
| В чем причина отсутствия кода ошибки узнать не удалось, но предполагая что ошибка таки WSAENOBUFS, использовав статью http://support.microsoft.com/kb/201213/en-us , удалось избавиться от появления ошибки. Фактически я отключил буферизацию сокета на отправку
Вероятнее всего дело было в переполнении буфера отправки. Нет буфера, нет переполнения |
| Автор: Олег2005 27.9.2011, 20:28 | ||
| Странно, почему вы использовали третий способ: Use the socket in nonblocking or asynchronous mode. Break large-size data blocks into small ones and specify a relatively small buffer in send for blocking sockets, preferably no larger than 64K. Set the SO_SNDBUF socket option to 0 (zero) to allow the stack to send from your application buffer directly.
Стандартный буфер сокета для TCP в винде - Default: 17520 байт Вот отсюда и проблемы около 20Кб. Есть несколько вариантов посмотреть getsockopt() размер буфера и убедиться, что он достаточен. Установить больший - если надо. У вас же передаются блоки по 4 к - это очень мало для переполнения стандартного буфера. Единственный вариант - модуль TCP - не может передать в буфер сетевой карты - потому как она еще не отправила предыдущие данные. Это может быть при сильной перегрузке сети. Во всяком случае не все так очевидно. Можно еще слать с задержкой - скажем 10 миллисекунд в sleep |
| Автор: Alexeis 27.9.2011, 22:34 |
Проверял, там размер 8кб, видимо он сравнял его с буфером приема сервера, потому что там тоже 8кб. Это как раз и странно, что успевает отправиться больше чем размер буфера. Загрузки сети ни какой, потому что сервер соединен с клиентом напрямую витой парой. >Break large-size data blocks into small ones and specify a relatively small buffer in send for blocking sockets, preferably no larger than 64K Так 4Кб как раз и соответствует описанию. Так что тут нечего было менять. Делал, именно так и выяснил. Если задержка 50мс, то нормально отправляется, если 10мс, то успевает переполниться. Однако в режиме с отключенным буфером скорость передачи выше чем с задержкой 50мс. Вообще, не охота играть с таймерами, поскольку задержки по пересылу врядли стабильны во времени. Когда больше, когда меньше. |
| Автор: Олег2005 27.9.2011, 22:55 |
| В общем проблема понята и решена. |
| Автор: Alexeis 27.9.2011, 22:58 |
Не совсем. Меня мучает вопрос, почему код ошибки не возвращается никакой. Слабо вериться что это глюк семерки, пусть даже 64х битной. |