Вопросы о длине сокетов - PullRequest
2 голосов
/ 15 ноября 2010

У меня есть пара вопросов, связанных со следующим кодом:

char buffer[256];
memset(buffer,0,256);

read(socket_fd,buffer,255);

Вопросы:

  1. Почему я читаю 255, а не 256?
  2. ДавайтеСказать, что я хочу отправить слово: «Круто» с клиента на сервер.Сколько байтов я должен написать «на клиенте» и сколько байтов я должен прочитать «на сервере»?

Я действительно запутался.

Ответы [ 3 ]

8 голосов
/ 15 ноября 2010

У вас уже есть хорошие ответы, но я думаю, что есть концепция, которую мы должны объяснить.

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

Итак, как мы разграничиваем сообщения? Есть три простых способа (и, конечно, множество других, не очень простых):

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

2 Разделительные символы или строки : Если вы отправляете текст, читаемый человеком, вы можете разграничивать свои сообщения так же, как вы разграничиваете строки в ваших char*: поставить символ 0 в конце. Таким образом, когда вы читаете 0, вы знаете, что сообщение закончилось, а все остальные данные в потоке принадлежат другому сообщению.

Это нормально для текста ascii, но когда дело доходит до произвольных данных, это также довольно жестко: есть символ или последовательность символов, которые ваши сообщения не могут содержать (или ваша программа запутается в том, где сообщение заканчивается).

3 Заголовки сообщений : Это лучший подход для сообщений произвольной длины с произвольным содержимым. Перед отправкой любых фактических данных сообщения отправьте заголовок фиксированной длины (или используйте метод номер 2, чтобы отметить конец заголовка), указав метаданные о вашем сообщении. Например, это длина.

Скажем, вы хотите отправить сообщение «Круто», как вы сказали. Хорошо, сначала отправьте байт (или 2-байтовое короткое, или 4-байтовое целое число, или что-то еще), содержащий «4», длину сообщения, и получите его на другом конце. Вы знаете, что до того, как поступит какое-либо сообщение, вы должны прочитать 1 байт (или 2o, или 4, или что угодно), поэтому сохраните это где-нибудь и затем прочитайте оставшиеся указанные байты.

Очень простой пример:

struct mheader {
    int length;
};

(...)
struct mheader in_h;
read(fd, &in_h, sizeof(struct mheader);

if (in_h.length > 0)
    read(fd, buffer, in_h.length)

Надеюсь, это поможет. Удачи!

3 голосов
/ 15 ноября 2010

Вы смотрите на возвращаемое значение от read(); он говорит вам, сколько байтов было прочитано.

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

Вам не нужно использовать 255 в чтении, если вы определенно не хотите иметь возможность поставить NUL в конце - но так как вы знаете, сколько байтов было прочитано, вы все равно не пойдете дальше. Итак, 255 - это страховой полис от невнимательности со стороны программиста.

memset() также является в большинстве случаев страховым полисом от небрежности со стороны программиста - он на самом деле не нужен, если только вы не хотите скрыть предыдущие конфиденциальные данные.

3 голосов
/ 15 ноября 2010
  1. Так что буфер сохраняет значение NUL в конце, как дополнительную страховку от переполнения строки.Чтение 256 позволит перезаписать его.

  2. Вы должны написать пять байтов.Либо напишите "Cool\0", либо напишите 4 (длина) с последующими 4 символами в «Cool».Прочитайте все это и выясните длину после.

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