Повреждение данных в memcpy

0

В настоящее время я работаю над проектом, используя сокеты через WinSock, и столкнулся с особой проблемой. Я приложу код, прежде чем начинать объяснять.

#include "Connection.h"


Connection::Connection(SOCKET sock, int socketType)
    : m_sock(sock), m_recvCount(0), m_sendCount(0), m_socketType(socketType)
{
    printf("Succesfully created connection\n");
}


Connection::~Connection(void)
{
    printf("Closing socket %d", m_sock);
    closesocket(m_sock);
}

void Connection::ProcessMessage(const NetMessage *message){
    printf("Got network message: type %d, data %s\n", message->type, message->data);
}


bool Connection::ReadSocket(){
    // Call this when the socket is ready to read.
    // Returns true if the socket should be closed.

    // used to store count between the sockets
    int count = 0;

    if(m_socketType == SOCK_STREAM){
        // attempt to read a TCP socket message
        // Receive as much data from the client as will fit in the buffer.
        count = recv(m_sock, &m_recvBuf[m_recvCount], sizeof(m_recvBuf) - m_recvCount, 0);
    }
    else if(m_socketType == SOCK_DGRAM){
        // attempt to read UDP socket message

        // temporarily stores details of the address which sent the message
        // since UDP doesn't worry about whether it connected to the
        // sender or not

        sockaddr_in fromAddr;
        int fromAddrSize = sizeof(fromAddr);

        count = recvfrom(m_sock, &m_recvBuf[m_recvCount], sizeof(m_recvBuf) - m_recvCount, 0, (sockaddr*) &fromAddr, &fromAddrSize);
    }
    else{
        printf("Unknown socket type %d\n", m_socketType);
        return true;
    }


    if (count <= 0)
    {
        printf("Tried to receive on socket %d and got %d bytes\n", m_sock, count);
        printf("Client connection closed or broken\n");
        return true;
    }

    // if we get to this point we have essentially received a complete message
    // and must process it

    printf("Received %d bytes from the client (total %d)\n", count, m_recvCount);
    m_recvCount += count;

    // Have we received a complete message?
    // if so, process it
    if (m_recvCount == sizeof NetMessage)
    {
        ProcessMessage((const NetMessage *) m_recvBuf);
        m_recvCount = 0;
    }

    return false;
}

bool Connection::WriteSocket(){
    // Sends the data in the send buffer through the socket

    int count;

    if(m_socketType == SOCK_STREAM){
        // attempt to read TCP socket message
        count = send(m_sock, m_sendBuf, m_sendCount, 0);
    }
    else if(m_socketType == SOCK_DGRAM){
        // attempt to read UDP socket message
        count = sendto(m_sock, m_sendBuf, m_sendCount, 0, 0, 0);
    }
    else{
        // unhandled type of socket, kill server
        printf("Unknown socket type %d", m_socketType);
        return true;
    }

    if (count <= 0)
    {
        // we have received an error from the socket
        printf("Client connection closed or broken\n");
        return true;
    }

    m_sendCount -= count;
    printf("Sent %d bytes to the client (%d left)\n", count, m_sendCount);
    printf("Data: %s", m_sendBuf);

    // Remove the sent data from the start of the buffer.
    memmove(m_sendBuf, &m_sendBuf[count], m_sendCount);

    return false;
}

bool Connection::WantWrite(){
    if(m_sendCount > 0){
        return true;
    }

    return false;
}

bool Connection::WantRead(){
    return true;
}

bool Connection::SetMessage(const NetMessage *message){
    // store contents of the message in the send buffer
    // to allow us to send later
    if (m_sendCount + sizeof(NetMessage) > sizeof(m_sendBuf))
    {
        return true;
    }

    memcpy(&m_sendBuf, message, sizeof(message));
    m_sendCount += sizeof(NetMessage);

    return false;
}

и протокол

/* Definitions for the network protocol that the client and server use to communicate */

#ifndef PROTOCOL_H
#define PROTOCOL_H

// Message types.
enum MessageType
{
    MT_UNKNOWN = 0,
    MT_WELCOME = 1,
    MT_KEYPRESS = 2,
    MT_CHATMESSAGE = 3
};

// The message structure.
// This is a "plain old data" type, so we can send it over the network.
// (In a real program, we would want this structure to be packed.)
struct NetMessage
{
    MessageType type;
    char* data;

    NetMessage()
        : type(MT_UNKNOWN)
    {
    }
};

#endif

По существу протокол содержит определение сообщений, которые клиент и сервер бросают друг другу. Проблема, с которой я столкнулась, заключается в том, что в connection.cpp строке 132 (memcpy) сообщение становится искаженным в sendBuf.

http://imgur.com/MekQfgm,9ShRtHi

На изображении выше показано, что происходит. Как сказано в протоколе.h, структура является POD, поэтому, когда я делаю memcpy, она должна передавать количество байтов, которое хранится в структуре (например, тип сообщения должен быть 1 байт, за которым следуют 7 или 8 байтов данных, в примере).

Может кто-нибудь пролить некоторый свет на это? Это сводит меня с ума.

  • 3
    Вы должны отредактировать код в своем сообщении. Внешние ссылки портятся.
  • 0
    Я просто подумал, что если бы это был класс, было бы немного здорово пометить код. Постараюсь, хотя, ура.
Теги:
winsock
winsock2

1 ответ

4
Лучший ответ

Строка, которую вы написали, скопирует 4 байта (sizeof (pointer)) на 32-битные системы:

memcpy(&m_sendBuf, message, sizeof(message));

что вы, вероятно, имели в виду:

memcpy(&m_sendBuf, message, sizeof(NetMessage));

Редактировать:

Кроме того, как заметил комментатор, ваш тип данных НЕ является POD. Он содержит указатель. Вы передаете этот указатель. В целевой системе он укажет на то же место в ОЗУ, но там ничего не будет. Вам необходимо сделать свой тип данных POD с помощью массива или вам нужно найти способ передачи указанных данных. Вы можете добиться этого, передав тип, длину и количество символов. Это означает, что ваш получатель НЕ может полагаться на сообщения фиксированного размера.

  • 0
    Спасибо за быстрый ответ, к сожалению добавление, которое все еще вызывает ту же проблему, сообщение искажено в буфере.
  • 0
    @jogojapan, как бы я поступил об этом?
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню