9

I have a question for you.

I have this class:

`

#define DIMBLOCK 128
#ifndef _BLOCCO_
#define _BLOCCO_

class blocco
{
    public:
        int ID;
        char* data;


        blocco(int id);
};

#endif




blocco::blocco(int id)
{
    ID = id;
    data = new char[DIMBLOCK];
}

`

and the application has a client and a server. In the main of my server I instantiate an object of this class in this way: blocco a(1);

After that I open a connection between the client and the server using sockets. The question is: how can I send this object from the server to the client or viceversa? Could you help me please?

rosekarma
  • 117
  • 1
  • 1
  • 12
  • Socket code is likely going to be required. And even then unless you're setting up an elaborate RPC system the best you'll get is a *copy* (which may be all you need). – WhozCraig Aug 29 '13 at 17:22

3 Answers3

16

It's impossible to send objects across a TCP connection in the literal sense. Sockets only know how to transmit and receive a stream of bytes. So what you can do is send a series of bytes across the TCP connection, formatted in such a way that the receiving program knows how to interpret them and create an object that is identical to the one the sending program wanted to send.

That process is called serialization (and deserialization on the receiving side). Serialization isn't built in to the C++ language itself, so you'll need some code to do it. It can be done by hand, or using XML, or via Google's Protocol Buffers, or by converting the object to human-readable-text and sending the text, or any of a number of other ways.

Have a look here for more info.

Community
  • 1
  • 1
Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234
  • So, it isn't possible to do something like that: ret = send(sock, reinterpret_cast(&a), sizeof(blocco),0);? – rosekarma Aug 29 '13 at 17:23
  • 1
    No. That won't work for a number of reasons... for one, it won't follow pointers (e.g. the receiver of a blocco that was sent that way would receive the value of the (data) pointer rather than the characters that (data) points to, which wouldn't be useful). It also doesn't correctly handle padding and endian-ness issues. – Jeremy Friesner Aug 29 '13 at 17:59
  • @rosekarma What good would that do? How would you write code to receive the data given that you would have literally no idea what bytes you had sent to it. To write code to receive the data, the first thing you'd need to know is how many bytes encode the ID. But you don't even know that -- and, worse, it will change if you change the compiler, platform, etcetera. – David Schwartz Feb 12 '17 at 20:25
3

you can do this using serialization. This means pulling object into pieces so you can send these elements over the socket. Then you need to reconstruct your class in the other end of connection. in Qt there is QDataStream class available providing such functionality. In combination with a QByteArray you can create a data package which you can send. Idea is simple:

Sender:

QByteArray buffer;
QDataStream out(&buffer);
out << someData << someMoreData;

Receiver:

QByteArray buffer;
QDataStream in(&buffer);
in >> someData >> someMoreData;

Now you might want to provide additional constructor:

class blocco
{
    public:
        blocco(QDataStream& in){
            // construct from QDataStream
        }

        //or
        blocco(int id, char* data){
            //from data
        }
        int ID;
        char* data;


        blocco(int id);
};

extended example

4pie0
  • 29,204
  • 9
  • 82
  • 118
0

I don't know how much flak I'll get for this, but well I tried this and though I should share it. I am a beginner at socket programming so don't get pissed off.

What I did is I created an array of characters which is of the size of the class (representing the block of memory at the server side). Then I recved the block of memory at the client side and typecast that block of memory as an object and voila!! I managed to send an object from client to server.

Sample code:

blocco *data;
char blockOfData[sizeof(*data)];

if(recv(serverSocket, blockOfData, sizeof(*data), 0) == -1) {
    cerr << "Error while receiving!!" << endl;
    return 1;
}

data = (blocco *)blockOfData;

Now you can do whatever you want with this data using this as a pointer to the object. Just remember do not try to delete/free this pointer as this memory is assigned to the array blockOfData which is on the stack.

Hope this helps if you wanted to implement something like this.

PS: If you think what I've done is poor way of coding please let me know why. I don't know why this is such a bad idea(if it is in fact a bad idea to do this). Thanks!!

  • If you want to see why that approach doesn't work, try printing out the character string pointed to by the 'data' member item of the 'received' blocco object after recv() returns. You'll find that the string did not get transferred across, and you'll either print out garbage or (more likely) your program will crash when it tries to dereference data's pointer, which is set to point to an address that was valid in the sender's memory-space but not in the receiver's memory-space. – Jeremy Friesner Feb 12 '17 at 23:00
  • I implemented this on my macbook and ran both the client and server on the same machine. I was successfully able to access the data, and did not face any crashes/garbage value issue. Maybe if I try to do this across multiple systems with differing endian systems I'll have a problem? – Siddharth Gupta Feb 13 '17 at 09:14
  • I get your point now, if I have pointers I'll face these issues. Although if I have a string (which I did in my code), then I won't face these issues. – Siddharth Gupta Feb 13 '17 at 09:22
  • Most string classes contain a pointer internally, so you'll likely still face that issue. Even if you didn't, though, you'd still face the other issues (endian-ness differences, word-size differences, struct-padding differences) except under specific circumstances (i.e. except when both the sending and the receiving program were compiled for the same CPU architecture and the same OS, using the same compiler with the same settings) – Jeremy Friesner Feb 13 '17 at 15:26