tags:

views:

79

answers:

4

My server and client are running on the same machine so I dont have endian issues etc. I need something that works on both vc++ and g++ and possibly the simplest way. What can I send the struct with?

Edit

struct Info
{
     int**   fields; 
     char**  field_names;
};
+1  A: 

Look at Boost.Serialization, here's a fairly trivial example I posted in another question

#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/string.hpp>

#include <string>

struct Message
{
    std::string _a;
    std::string _b;

    template <class Archive>
    void serialize(
            Archive& ar,
            unsigned int version
            )
    {
        ar & _a;
        ar & _b;
    }
};

int
main()
{
    Message msg;
    msg._a = "hello";
    msg._b = "world";
    std::ostringstream os;
    boost::archive::text_oarchive ar( os );
    ar & msg;
}

Note the serialization library has MUCH more capability than this. It can serialize pointers, references, containers, and many objects in other Boost libraries. My example here shows intrusive serialization, if you cannot modify your struct, there are ways to serialize non-intrusively as well.

Sam Miller
My struct is as followsstruct Info{ int **fields; char **field_names;};isn't boost an overkill?
Rajesh
If you are already using boost, it most likely is not overkill to use Boost.Serialization. It may be overkill using it just for this purpose, that's up to you.
Sam Miller
Yea..I need something just for serialization.
Rajesh
A: 

You will need to make sure that data members you're using in VC++ and G++ have the same byte size and alignment.

If you have a data member of a variable length the best way to transfer it over a socket is to send the size as well.

Lets say you have a structure like this:

struct DataStruct
{
   int x;
   char* message;
   short messageLen;
}

You can send the data over the socket, member per member, in a specified format because you know the size of non predefined size members.

Integers are 4 bytes in both G++ & VC++; characters are both 1 byte; shorts are 2 bytes.

First transfer the x value, then the messageLen var and use this variable to create the variable buffer size on the other side. You can then write the message data into the char*.

Chaoz
A: 

The struct that you have has pointers to data rather then the data itself. If you were to use POD types (i.e. int and char[]) in the struct then it could be sent directly on a socket.

There may be a additional bytes that are transmitted due to alignment/padding within the structure but if you are ok with that then your good to go. This works because you are running the client and server on the same OS. If different OS's were involved the alignment/padding would pose an issue.

boost::asio has some very simple examples that you can use.

skimobear
A: 

You can declare a static unsigned char like so:

#define MSGBUFSIZE  512
static unsigned char ClientSendBuf[MSGBUFSIZE];

then copy your structure into the array like so:

memmove(&ClientSendBuf[2], &struct, sizeof(struct));

now this where it is implementation specific next. I am using Borland C++ so my sending acts like so:

ClientSocket->Socket->SendBuf(ClientSendBuf, ClientSendBuf[0]+CRC16SIZE);

The reason I use ClientSendBuf[0] is because the size of my message is stored in ClientSendBuf[0] like so:

ClientSendBuf[0] = 4 + sizeof(struct);             //Byte Count

(Note: Replace struct with the name of your struct)

I also add a CRC check to the end of my message like so:

#define CRC16SIZE   2

...

cs = CheckSum((unsigned char *)ClientSendBuf, ClientSendBuf[0]);
    memmove(&ClientSendBuf[ClientSendBuf[0]], &cs, CRC16SIZE);

...

unsigned short __fastcall TFormMenu::CheckSum(unsigned char *p, int length)
{
    int i;

    for (cs = 0, i = 0; i < length; i++) {
        cs += p[i];
    }
    return cs;
}

Basically all this simple CRC check is doing is summing all the bytes to determine that the correct number of bytes is sent. If the data should get mangled (which is common through buggy WiFi connections by the way), then the server should throw a CRC error.

This all assumes you have a POD struct. The static part is not necessary, but how I did it in my particular application. I also glossed over some details. Post in the comments if you have questions. YMMV.

0A0D