чтение буфера из сокета - PullRequest
1 голос
/ 19 июня 2010

Я пишу простой сервер / клиент в c, где сервер временно сохраняет сообщение от клиента и извлекает его, когда клиент запрашивает его.

Проблема в том, что, когда клиент получает сообщение от сервера, буфер действует довольно странно. Все, что я сделал, это прочитал столько, сколько получил от сервера и напечатал его на экране, но каким-то образом буфер был перезаписан больше, чем максимальный размер буфера

в клиенте

while((byteRead = recv(ssock, buffer, MAXBUF, 0)) > 0)
{
   if(byteRead <= 0)
       break;
    printf("%s", buffer);
}

где MAXBUF - 256. Он содержит несколько мусоров, поэтому я проверил размер строки в буфере и удивительно

printf("%d READ vs %d buffer strlen \n", byteRead, strlen(buffer))

покажи мне, что byteRead равен 256, а длина строки буфера равна 262.

Есть идеи ??

P.s на стороне сервера, он правильно читает файл и отправляет его в сокет.

Ответы [ 3 ]

16 голосов
/ 19 июня 2010

recv не ставит нулевой терминатор в конце строки (в то время как printf %s предполагает, что он есть).

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

5 голосов
/ 19 июня 2010

Проблема здесь в том, что buffer не заканчивается на NULL значением recv().Фактически, recv только помещает необработанные данные сокета в буфер.Если он получает 256 байтов данных, то все, что последует за ним, может быть нулевым символом (например, как на вашем сервере) или может быть чем-то другим (как на вашем клиенте).Это артефакт выполнения программы, а не того, как вы его запрограммировали.

Самый простой и быстрый способ исправить это:

  1. Выделить buffer с размером MAXBUF + 1.+1 будет для дополнительного пустого символа.
  2. Непосредственно перед printf, добавьте нулевой символ в buffer[bytesRead].

Итак, все сказано:

buffer = malloc((MAXBUF + 1) * sizeof(char));          // NEW

while((byteRead = recv(ssock, buffer, MAXBUF, 0)) > 0)
{
    if(byteRead <= 0)
        break;
    else {
        buffer[bytesRead] = '\0';                      // NEW
        printf("%s", buffer);
    }
}
1 голос
/ 19 июня 2010

Да.

strlen () ищет ближайший терминатор NULL, как в обычной строке C.

recv () не имеет ничего общего с нулевым терминатором и не будет добавлять его. Таким образом, вызов strlen неверен и может даже привести к сбою вашей программы при несанкционированном чтении.

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