2010-11-15 2 views
2

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

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

read(socket_fd,buffer,255); 

вопросы:

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

Я действительно смущен.

+3

Вы не наполовину в замешательстве, так как я –

ответ

8

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

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

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

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

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

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

3 Заголовки сообщений: Это лучший подход для произвольной длины, произвольных сообщений контента. Перед отправкой любых фактических данных сообщения отправьте заголовок фиксированной длины (или используйте метод nr 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) 

Надеется, что это помогает. Удачи!

+0

Очень хорошее объяснение. Благодаря! –

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

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

3

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

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

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

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

Смежные вопросы