2009-04-15 2 views
5

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

«Привет, мир! Привет, мир! Привет, мир! Привет, мир! Hello World! Hello World! Hello World!»

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

Благодаря

+0

Вы отказали свою строку? «Hello World! \ 0» – Alan

ответ

7

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

int count = read(...); 
// buffer[0 .. count - 1] contains the appropriate data. 
+0

И только чтобы сообщить вам, сервер, получающий данные, выполнен в C# – QAH

+0

QAH: Это также верно для сокетов C#, Socket.Receive. –

4

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

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

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

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

6

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

0

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

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

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

+0

UDP - это протокол пользовательских дейтаграмм - он не имеет ничего общего с ненадежностью в своем имени. Вы правы, что это относительно ненадежно, хотя :) –

0

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