С++ Winsock2 recv recv

Итак, я пишу чат Windows, и в целях тестирования моя клиентская программа отправляет сообщение «привет» на сервер каждые 300 мс.

Первые пару сообщений приходят хорошо, но потом, как ни с того ни с сего, они начинают становиться мусором- screenshot

Очевидно, я хочу это исправить и прошу вашей помощи :) Вот мой код:

Функция отправки:

bool Target::Send(char *message)
{
    int length = strlen(message);
    int result = send(this->ccSock, (char*)&length, sizeof(int), 0);
    if (result <= 0)
        return false;

    Sleep(10);

    result = send(this->ccSock, message, length, 0);
    return ((result > 0) ? true : false);
}

Функция получения:

Message Server::Receive(SOCKET socket)
{
    int length = 0;
    int result = recv(socket, (char*)&length, sizeof(int), 0);

    Sleep(10);

    char *rcvData = new char[length];
    result = recv(socket, rcvData, length, 0);

    return { rcvData, result };
}

Структура сообщения:

struct Message {
    char *msg;
    int size;
};

Основной код отправки:

while (true)
{
    if (!target->Send("hello"))
    {
        cout << "Connection broken\n";
        target->Clean();
        break;
    }

    Sleep(300);
}

Основной код получения:

while (target.sock)
{
    Message message = server->Receive(target.sock);
    if (message.size > 0)
        cout << message.msg << " (" << message.size << ")\n";
    else
    {
        cout << "Target disconnected\n";
        server->Clean();
        break;
    }

    Sleep(1);
}

Я был бы очень признателен за вашу помощь, а также объяснение, почему это происходит!


person Community    schedule 30.08.2016    source источник
comment
TL;ДР; Вы позаботились о правильном нуле-завершении вашего буфера recv?   -  person πάντα ῥεῖ    schedule 30.08.2016
comment
(result > 0) ? true : false эквивалентно result > 0.   -  person molbdnilo    schedule 30.08.2016
comment
о.. не знал, что после 2 лет программирования   -  person    schedule 30.08.2016


Ответы (1)


Ваш буфер не завершается нулем. Поэтому, когда вы пытаетесь распечатать его с помощью std::cout, происходит переполнение буфера. Правильная версия кода приема должна быть:

char *rcvData = new char[length+1];
result = recv(socket, rcvData, length, 0); 
rcvData[length] = '\0';

Кроме того, вы никогда не освобождаете выделенный буфер памяти, поэтому ваш код пропускает его при каждом вызове Receive.

person Ari0nhh    schedule 30.08.2016
comment
Спасибо, сработало :) Еще добавил memset(rcvData, 0, sizeof(char) * (length + 1)); после строки new char[] - person ; 30.08.2016
comment
memset() это излишество, оно вам вообще не нужно. И вам не нужно завершать буфер нулем, если вы используете std::setw(), чтобы сообщить std::cout максимальное количество символов для вывода: std::cout << std::setw(message.size) << message.msg; Однако я бы предложил хранить данные в std::string вместо char[], это позаботится о проблема вывода и проблема управления памятью. - person Remy Lebeau; 30.08.2016