Archived

This topic is now archived and is closed to further replies.

Xelot

send with winsock

Recommended Posts

Im using Winsock 2 with VC. I read some where that its possible to send any type (such as a struct that I make) with Winsock. I look at the prototype for send() and sendto() in WSAPI22.DOC and they both take a pointer to a char for what to send. How can I send a struct instead of a char array?

Share this post


Link to post
Share on other sites
This code should work.
You can use a similar system for Recieveing data as well.


  
#define SAFERELEASE(x) if (x != NULL){delete x; x = NULL;}


////////////////////////////////////////////////////////

// Send Struct Returns True if It''s Successful

////////////////////////////////////////////////////////

bool SendStruct(void* pData, int nSize, socket socketID)
{

// Locals

char* byData = NULL; // Initalize a char array and set to NULL


// Allocate String

byData = new char[nSize];

// Copy Data. NOTE! Does Not Swap Endian!

memcpy(byData, pData, nSize);

//Send String

if (send(m_Connection, bySendBuffer, nSize, NULL) != nSize)
{
SAFERELEASE(bySendBuffer);
return false;
}

SAFERELEASE(bySendBuffer);
return true;
}

Share this post


Link to post
Share on other sites
this is better and doesnt require the memcpy
just cast it to a char*
  
struct MyStruct
{
// data stuff in here

};
.
.
.
MyStruct data;
.
.
.
send(m_Connection, (char*)&data, sizeof(MyStruct), NULL);



"I pity the fool, thug, or soul who tries to take over the world, then goes home crying to his momma."
- Mr. T

Share this post


Link to post
Share on other sites
Why would send miss something? You just give it a pointer to the data, and then the size of the buffer, and sizeof() just returns the size of the struct.

Of course you waste a few bytes here and there if alignment rules actually kick in. You might want to set the structures to be byte packed (using #pragmas or attributes, depending on the compiler).

I''m a bit confused though... send() should really take a void * pointer, because it completely ignores the format of the data that is being sent. Prototypes using char * are logically broken (or does this mean that MS assume you''re sending text and therefore scan the data for private data? ).

cu,
Prefect

One line of sourcecode says more than a thousand words.

Share this post


Link to post
Share on other sites
Thanks people for your help. I got sending and receiving a struct to work but I have a problem. I am writing a high level Winsock wrapper. I want my send function to take only one parameter - a pointer to the data. If I do sizeof(Type) that works but my send function wont know what type it is so I have to do sizeof(Object) but it misses some bytes that way. How should I do it?

Share this post


Link to post
Share on other sites
Well, you have to pass the size of the data along with the data itself.

The only possible alternative would be to use a C++ wrapper class like this:

  
class CData {
public:
virtual int GetSize() = 0;
virtual void *GetData() = 0;
};


You would then of course inherit this class for the various different types (like int, structs, etc...), overloading the GetSize and GetData members.

Your send() function would then just take a pointer to CData. It''d then call GetSize and GetData to get the information it needs to send the packet.

However, I doubt that this is really worth it.

cu,
Prefect

One line of sourcecode says more than a thousand words.

Share this post


Link to post
Share on other sites
I am also currently experimenting my way through a winsock program, and I have found that using a single union to represent all of the different types that can be sent, coupled with a packet type byte and a function that determines packet size from the type works very well.

E.g.
  union Packet {
BYTE id;

struct {
BYTE id;
char textdata[10]; //or whatever

} packet1;

struct {
BYTE id;
double doubleVar; //or whatever

int etc;
} packet2;
}


Then, when I want to send a packet:
  Packet pack;
pack.id = PACK_ID_PACK1; //constant defined elsewhere

strcpy(pack.packet1.textdata, "hello");
send(socket, (char *)&pack, getSizeOfPacket(PACK_ID_PACK1), 0);


Then when receiving, I first recv just one byte to get the packet ID number, and figure out how much more data I have to receive from getSizeOfPacket. Then I recv the rest of the packet and decide what to do with it based on the packet type. I just like the simplicity of using one type for all of the packets, while retaining the flexibility to send any kind of data you want.

Share this post


Link to post
Share on other sites