С ++ сокет 256-байтовый буфер - PullRequest
5 голосов
/ 15 апреля 2009

Я пытаюсь использовать некоторое сетевое программирование сокетов на C ++. Я пытаюсь отправить текст "Hello World!" на сервер с помощью функции C ++ send (). Сначала я установил размер буфера 13, так как "Hello World!" всего 12 символов (вам нужно сделать это на один символ больше). Функция отправки только отправляет символы на сервер, если я отправляю их около 7 раз. И когда он, наконец, приходит на сервер, он выглядит так:

"Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World!"

Теперь вот забавная часть. "Привет, мир!" предложение отправляется немедленно, если я установил размер буфера равным 256 (символ буфера [256];). Когда дело доходит до сервера, он показывает "Hello World!" с целой кучей места после двух слов. Почему это происходит и, если возможно, как я могу это исправить? Пожалуйста, дайте мне знать.

Спасибо

Ответы [ 5 ]

7 голосов
/ 15 апреля 2009

Когда вы вызываете read (или receive) с вашим буфером для чтения из сокета, возвращается целочисленное значение, которое указывает количество прочитанных байтов. Вы должны только взять это из буфера. Остальное не имеет значения:

int count = read(...);
// buffer[0 .. count - 1] contains the appropriate data.
6 голосов
/ 15 апреля 2009

Алгоритм Nagle обычно включен по умолчанию. Это объединит несколько маленьких пакетов в один. Выключение алгоритма Nagle позволит немедленно отправлять небольшие пакеты.

4 голосов
/ 15 апреля 2009

Существуют буферы для хранения данных, пока вы не будете готовы их отправить. Размер буфера отправки равен 256. До тех пор, пока через буфер не будет передано 256 символов, ваши данные не будут отправляться на другую сторону. Это можно исправить, вызвав метод очистки в буфере, когда вы будете готовы к отправке.

Для ясности, вы выполняете внутреннюю буферизацию, затем ОС (или библиотека) снова буферизуется, когда вы вызываете send () и передаете некоторые данные.

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

В качестве альтернативы, если вы находитесь в * nix, просто отключите алгоритм Nagle, чтобы ОС не буферизировала ваши маленькие пакеты. Или, когда вы настраиваете свой сокет, обязательно используйте опцию TCP_NODELAY

0 голосов
/ 16 апреля 2009

Программирование сокетов утомительно, подвержено ошибкам и не переносимо. Начните использовать библиотеки, такие как Boost или ACE , которые защищают вас от API низкого уровня C и предоставляют независимые от платформы абстракции.

0 голосов
/ 15 апреля 2009

Предполагая, что это сокет SOCK_STREAM, важно помнить, что базовый протокол TCP не поддерживает границ сегментов. То есть, когда вы вызываете send () несколько раз, все отправленные вами данные очень легко могут быть возвращены одним вызовом recv () на другом конце. Или данные, отправленные в одном вызове send (), могут быть возвращены в нескольких recv () на другом конце, например, если некоторые пакеты были задержаны из-за перегрузки сети. Это имеет основополагающее значение для дизайна TCP, и ваше приложение должно быть разработано соответствующим образом.

Кроме того, как отметил Мехрдад, вызов recv () возвращает количество байтов, которые были прочитаны с провода. Все, что находится после этой точки в буфере, является мусором, и данные не заканчиваются нулем.

Сокет SOCK_DGRAM использует UDP внизу, который полностью ориентирован на пакет, а не на поток, как TCP. Однако UDP не гарантирует надежность (U обозначает ненадежный), поэтому вам придется самостоятельно обрабатывать потерянные, дублированные, неупорядоченные и т. Д. Пакеты. Это намного сложнее, чем потоковый ввод-вывод.

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