2010-06-19 4 views
1

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

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

в клиенте

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

где MAXBUF 256. Это держать содержит некоторые garbages так я рассмотрел размер строки в буфере и удивительно

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

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

Любая идея ??

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

ответ

13

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

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

1

Да.

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

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

+0

ок я получил эту точку. Но на стороне сервера, когда клиент отправляет сообщение серверу через сокет, он получает правильно, и я не добавлял нулевой указатель. Даже я думал, что добавил нулевой указатель перед отправкой клиенту, он все еще показывает мусорные вещи; – REALFREE

+0

@REALFREE: Когда мы говорим о нулевом терминаторе, мы говорим о «nul» * character *, а не о указателе null *.Кроме того, в случае вашего сервера он может * появиться * работать из-за удачи, но вы делаете что-то неподобающее. – Artelius

4

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

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

  1. Выделяют buffer с размером MAXBUF + 1. +1 будет для дополнительного символа NULL.
  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); 
    } 
} 
Смежные вопросы