I'm currently working on a project using sockets via WinSock and have come across a peculiar problem. I'll attach the code before I start explaining.
#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's 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;
}
and the protocol
/* 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
Essentially the protocol holds the definition of the messages that the client and server throw around to each other. The problem I am having is that, in connection.cpp line 132 (memcpy), the message becomes garbled in sendBuf.
http://imgur.com/MekQfgm,9ShRtHi
The image above shows exactly what is happening. As said in protocol.h the struct is a POD so when I do memcpy it should transfer the number of bytes as is held in the struct (so for example the message type should be 1 byte, followed by 7 or 8 bytes of data, in the example).
Can anyone shed some light on this? It's driving me crazy.