@Zohei

C. Откуда мусор в конце строки (char)?

Добрый день.
Осваиваю си путем написания своего фтп клиент-сервера.

Код получение ответа сервера и его вывод:
char receiveData[DEFAULT_BUFLEN];
	memset(receiveData, 0, DEFAULT_BUFLEN);
	result = receive_data(receiveData);
	MessageBox(hWnd, (LPCSTR)receiveData, TEXT("123"), 0); // Без МУСОРА!!
	SendMessageA(hLogListBox, LB_ADDSTRING, 0, (LPARAM) receiveData); // с мусором!!
        SendMessage(hLogListBox, LB_ADDSTRING, 0, (LPARAM) receiveData); // с мусором!!

MessageBox показывает ответ нормально
220 FTP Server(Version 6.00LS) ready.
Но в листбоксе в конце строки присутствует мусор.
220 FTP Server(Version 6.00LS) ready.(МУСОР)

Функция receive_data
int receive_data(char *receiveData)
{
	char buffer[DEFAULT_BUFLEN];
	struct timeval timeout;
	int rc;
	fd_set fdr;
	
	FD_ZERO(&fdr);
	FD_SET(socket_desc, &fdr);
	timeout.tv_sec = 1; 
	timeout.tv_usec = 0;
	
	do {
        memset(buffer, 0, DEFAULT_BUFLEN);
        if (recv(socket_desc, buffer, DEFAULT_BUFLEN - 1, 0) < 0) {
            printf("recv failed: %d\r\n", WSAGetLastError());
			socket_desc_close();
			WSACleanup();
			return -1;
        }
        //printf("+ %s \r\n", buffer);
		rc = select(socket_desc + 1, &fdr, NULL, NULL, &timeout); 
    } while(rc);

	strcpy(receiveData, buffer);
	return 0;
}
  • Вопрос задан
  • 552 просмотра
Пригласить эксперта
Ответы на вопрос 1
@res2001
Developer, ex-admin
1. Вы полностью игнорируете размер прочитанных данных, которые возвращает recv.
recv - не обязуется прочитать то количество данных, которое вы ей передаете как размер буфера. Она возвращает реально прочитанное количество данных.

2. При получении информации по сети не гарантируется, что отправляемые данные придут все за один раз (и так же прочитаются recv), они могут фрагментироваться, задерживаться, сцепляться со следующими пакетами и т.п.
Разбор полученных данных ложится на принимающую сторону.

3. В данных, возвращаемых recv, обычно нет нулевого символа в конце строк. Т.е., если вы ждете строку, то для дальнейшей работы с полученными данными как со строкой вы должны сами обозначить конец строки - принудительно проставить нулевой символ. Для этого в приемном буфере у вас должно быть предусмотрено место для нулевого символа при любом размере полученных данных.
Без этого большинство функций, работающих со строками будут давать не правильный результат.

4. Если вы ждете строго определенный размер данных, то вы должны в коде предусмотреть чтение сокета до тех пор, пока не вычитаете нужное количество данных. При этом вызовов recv может быть несколько (см.п.1, 2).

5. Если вы ждете в прочитанных данных какого-то завершающего символа (конца строки как в FTP), то вы должны самостоятельно проверять наличие этого символа(ов) - recv за вас это не сделает. Если в текущих полученных данных от recv нет конца строки - это не значит, что произошла ошибка. Это значит, что прочитаны не все данные и нужно еще их дочитывать.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы