c++ Object Serialization and transfer over Socket

Hi all!

I need Serialization of basic class object to send it as binary over Socket.

I managed to achieve this but partially. It works fine and at some point i get exception when reading back from the binary file into the object. Would please some look at my code and explain what i am missing? I know it is just small tiny thing cos it works and then crashes :) sounds robust, is it?

Here is the code I use:

1.My class and the way I overwrite << to write to the binary file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class COrderDetails  //To store and manage order related information
{
public:
				
	int 			ticket, event_id, magic, type, open_time, close_time, expire_time;
	double			lots, open_price, close_price, sl, tp;
	char		        comment[32], symbol[16];

	//Constructor
	COrderDetails()
	{
		ticket=0; event_id=0; magic=0; type=0; magic=0; open_time=0; close_time=0; expire_time=0;
		lots=0; open_price=0; close_price=0; sl=0; tp=0;
	}
	//Destructor
	~COrderDetails(){ return; }
	
	//Serilization/Deserilization
	friend std::ofstream& operator<<( std::ofstream &stream, const COrderDetails &v );
};

// write to the stream
std::ofstream& operator<<( std::ofstream &stream,  const COrderDetails& v )
{
	stream.write( (char*)&v.close_price, sizeof(v.close_price) );
	stream.write( (char*)&v.close_time, sizeof(v.close_time) );
	stream.write( v.comment, sizeof(v.comment) );
	stream.write( (char*)&v.event_id, sizeof(v.event_id) );
	stream.write( (char*)&v.expire_time, sizeof(v.expire_time) );
	stream.write( (char*)&v.lots, sizeof(v.lots) );
	stream.write( (char*)&v.magic, sizeof(v.magic) );
	stream.write( (char*)&v.open_price, sizeof(v.open_price) );
	stream.write( (char*)&v.open_time, sizeof(v.open_time) );
	stream.write( (char*)&v.sl, sizeof(v.sl) );
	stream.write( v.symbol, sizeof(v.symbol) );
	stream.write( (char*)&v.ticket, sizeof(v.ticket) );
	stream.write( (char*)&v.tp, sizeof(v.tp) );
	stream.write( (char*)&v.type, sizeof(v.type) );
	
	return stream;
}


2. Actual writing i do as append cos i may have multiple instances to write:
1
2
3
4
5
6
7
        ...
        COrderDetails pOrderDetails;
        ... //Filling of class with data skiped
        ofstream file;
	file.open(FILENAME_STATUS, ios::app | ios::out | ios::binary );
	file << pOrderDetails;
	file.close();

3. After i got the file i read it as block and send it over the socket
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
        ...	
        ifstream::pos_type size;
	char * memblock;

	ifstream file;
		file.open(FILENAME_STATUS, ios::in|ios::binary|ios::ate);

		size = file.tellg();
		memblock = new char[(int)size];
		file.seekg (0, ios::beg);
		file.read (memblock, size);
		file.close();

		int iRes = Send(socket,memblock,(int)size);
		
		delete[] memblock;
		return iRes;
         ...


4. On the other side
I first stream to file on the remote pc byte wise. I could not find other working way. Then i open this new recv file and read variable by variable. The way i overwrite >> here is this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
	friend std::ifstream &operator>>( std::istream &stream, const COrderDetails &v );
};

// read to the stream
std::ifstream &operator>>( std::ifstream &stream, const COrderDetails &v )
{
	stream.read( (char*)&v.close_price, sizeof(v.close_price) );
	stream.read( (char*)&v.close_time, sizeof(v.close_time) );
	stream.read( (char*)&v.comment, sizeof(v.comment) );
	stream.read( (char*)&v.event_id, sizeof(v.event_id) );
	stream.read( (char*)&v.expire_time, sizeof(v.expire_time) );
	stream.read( (char*)&v.lots, sizeof(v.lots) );
	stream.read( (char*)&v.magic, sizeof(v.magic) );
	stream.read( (char*)&v.open_price, sizeof(v.open_price) );
	stream.read( (char*)&v.open_time, sizeof(v.open_time) );
	stream.read( (char*)&v.sl, sizeof(v.sl) );
	stream.read( (char*)&v.symbol, sizeof(v.symbol) );
	stream.read( (char*)&v.ticket, sizeof(v.ticket) );
	stream.read( (char*)&v.tp, sizeof(v.tp) );
	stream.read( (char*)&v.type, sizeof(v.type) );

	return stream;
}


This is the actual loop code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void StatusMan(char *msg, DWORD dwBytesTransfered)
{
	//Stream recv data to file
	fstream file2;
	file2.open(STATUS_FILE, ios::out );
	for(unsigned long i=0;i<dwBytesTransfered;i++){file2 << msg[i];}
	file2.close();
	//Open file and move 2bytes to skip TAG
	ifstream file;
	file.open(STATUS_FILE, ios::in | ios::binary );	
	//Iterate as long as bytes recv
	while( true ){
		file.seekg(2, ios::cur);
		//Load data to order object
		COrderDetails order;
		file >> order;
		//Process curr order. Details loaded into object
		order.showData();
		//Move to the next order if any
		if( file.eof() ){break;}
		}
	file.close();
}


just to notice order.showData() in the code is some basic function to printf the class data to console i added to the class as method. And I move 2bytes because i separate record with 2byte TAG "S|" for instance.

Finally so far so good it works ok for small records numbers. Say 2-3 orders are recv and read 100% correctly but when file contains for instance 10 classes to be read exception rises at some point when reading. I check everything that came to my mind like: recv buffer len is OK 4 times larger than my file size. Order of reading of variable is same almost everything possible to my mind...

I'm stuck please help. I want to use this simple way not boost or others because it is simple class. No pointer to other classes or dynamics or etc. Just a elegant way to send the data over the socket and process it on the other side fast. It is 100 times better to load to class as phrase strings i hope you agree.

Hope someone will help.

Thanks
comment and symbol are arrays. You wrote them correctly but you're not reading them correctly.

Also, consider an alternative to writing to files - for instance return a std::string (it can contain null characters and others without causing problems) or a pointer to a new'd array that you can later delete.
Topic archived. No new replies allowed.