Serialisation of more than one object
-
Hi Sending objects over a wire from a client to a server. I 'serialise' the object on the client, send, via a Socket, and deserialise on server. Cool. Works a treat....for one object. Whilst the server is handling the object I've sent, I might have sent three or four more, so when the server finally gets round to reading the socket stream again, it pulls in byte[] containing multiple serialised objects. Throwing that at my deserialise method fails. Do I have to manually tokensize the byte[] before sending and then on the server parse for the tokens? This could be a) slow as the tokens could be very large and b) not guarenteed, as the tokens I use could actually be part of the data in the serialised object, which would cause the deserialise to split in the wrong place. Any ideas? Current code below
public void Go()//lovely method name!
{
//now we want some asynchronous reading here....
socket.BeginReceive(cs.RcvBuffer , 0 , cs.RcvBuffer.Length , SocketFlags.None , new AsyncCallback(ReadCallback), cs);
}protected void ReadCallback(IAsyncResult ar) { clientState cs = (clientState)ar.AsyncState; try { int recvMsgSize = cs.ClntSock.EndReceive(ar); if (recvMsgSize > 0) { cs.TotalBytes += recvMsgSize; Console.WriteLine("Thread {0} - ReadCallback(): total received {1} bytes", ID, cs.TotalBytes); **//next line is good if array only has one object in but fails, //which you'd expect if it has more...** SocketTest.MyTestClass m = Decode(cs.RcvBuffer); DoSomethingWithMyTestClass( m ); Go();//read from stream again...is this the best way? } } catch(SocketException se) { Console.WriteLine(se.ErrorCode + ":" + se.Message); } } public SocketTest.MyTestClass Decode(byte\[\] theByteArray) { Console.WriteLine("Decoding {0} bytes", theByteArray.Length); MemoryStream ms = new MemoryStream(theByteArray); BinaryFormatter bf1 = new BinaryFormatter(); ms.Position = 0; return (SocketTest.MyTestClass)bf1.Deserialize(ms); }
Regar
-
Hi Sending objects over a wire from a client to a server. I 'serialise' the object on the client, send, via a Socket, and deserialise on server. Cool. Works a treat....for one object. Whilst the server is handling the object I've sent, I might have sent three or four more, so when the server finally gets round to reading the socket stream again, it pulls in byte[] containing multiple serialised objects. Throwing that at my deserialise method fails. Do I have to manually tokensize the byte[] before sending and then on the server parse for the tokens? This could be a) slow as the tokens could be very large and b) not guarenteed, as the tokens I use could actually be part of the data in the serialised object, which would cause the deserialise to split in the wrong place. Any ideas? Current code below
public void Go()//lovely method name!
{
//now we want some asynchronous reading here....
socket.BeginReceive(cs.RcvBuffer , 0 , cs.RcvBuffer.Length , SocketFlags.None , new AsyncCallback(ReadCallback), cs);
}protected void ReadCallback(IAsyncResult ar) { clientState cs = (clientState)ar.AsyncState; try { int recvMsgSize = cs.ClntSock.EndReceive(ar); if (recvMsgSize > 0) { cs.TotalBytes += recvMsgSize; Console.WriteLine("Thread {0} - ReadCallback(): total received {1} bytes", ID, cs.TotalBytes); **//next line is good if array only has one object in but fails, //which you'd expect if it has more...** SocketTest.MyTestClass m = Decode(cs.RcvBuffer); DoSomethingWithMyTestClass( m ); Go();//read from stream again...is this the best way? } } catch(SocketException se) { Console.WriteLine(se.ErrorCode + ":" + se.Message); } } public SocketTest.MyTestClass Decode(byte\[\] theByteArray) { Console.WriteLine("Decoding {0} bytes", theByteArray.Length); MemoryStream ms = new MemoryStream(theByteArray); BinaryFormatter bf1 = new BinaryFormatter(); ms.Position = 0; return (SocketTest.MyTestClass)bf1.Deserialize(ms); }
Regar
Sorry, should have tried harder before posting....but it just clicked! Easy - pass down the number of bytes recieved to the decode, and keep decoding until the position in the memorystream exceeds the number of bytes passed New Code :
...snip.... if (recvMsgSize > 0) { cs.TotalBytes += recvMsgSize; Console.WriteLine("Thread {0} - ReadCallback(): total received {1} bytes", ID, cs.TotalBytes); //next line is good if array only has one object in but fails, //which you'd expect if it has more... Decode(cs.RcvBuffer , **recvMsgSize**); //DoSomethingWithMyTestClass( m ); public void Decode(byte[] theByteArray , **long SizeOfBuffer**) { Console.WriteLine("Decoding {0} bytes", **SizeOfBuffer**); MemoryStream ms = new MemoryStream(theByteArray); BinaryFormatter bf1 = new BinaryFormatter(); ms.Position = 0; **while (ms.Position < **SizeOfBuffer**) { SocketTest.Message m = (SocketTest.Message)bf1.Deserialize(ms); //ms.Position is updated each time we deserialise DoSomethingWithMyTestClass(m); }** }
Regards Malc *********************************************
-
Sorry, should have tried harder before posting....but it just clicked! Easy - pass down the number of bytes recieved to the decode, and keep decoding until the position in the memorystream exceeds the number of bytes passed New Code :
...snip.... if (recvMsgSize > 0) { cs.TotalBytes += recvMsgSize; Console.WriteLine("Thread {0} - ReadCallback(): total received {1} bytes", ID, cs.TotalBytes); //next line is good if array only has one object in but fails, //which you'd expect if it has more... Decode(cs.RcvBuffer , **recvMsgSize**); //DoSomethingWithMyTestClass( m ); public void Decode(byte[] theByteArray , **long SizeOfBuffer**) { Console.WriteLine("Decoding {0} bytes", **SizeOfBuffer**); MemoryStream ms = new MemoryStream(theByteArray); BinaryFormatter bf1 = new BinaryFormatter(); ms.Position = 0; **while (ms.Position < **SizeOfBuffer**) { SocketTest.Message m = (SocketTest.Message)bf1.Deserialize(ms); //ms.Position is updated each time we deserialise DoSomethingWithMyTestClass(m); }** }
Regards Malc *********************************************
You could add a header that contains the number of objects being transmitted and the size of each object in bytes. The tricky bit would be that since the number of objects being transmitted can vary, so too will the size of the header. An alternative would be to add each object being transmitted to a container and then serialize/transmit/deserialize the container and then deserialize each object in the container.
-
You could add a header that contains the number of objects being transmitted and the size of each object in bytes. The tricky bit would be that since the number of objects being transmitted can vary, so too will the size of the header. An alternative would be to add each object being transmitted to a container and then serialize/transmit/deserialize the container and then deserialize each object in the container.
They are being sent from the client one at a time, varying length. The stream gets concatonated at teh server side whilst I am handling a previous read. I sussed it out partially, as deserialise nicely moves the pointer in the memory stram to the start of the next object. My current issue is handling partial data. After calling BeginRecieve, EndReceive, my byte[] buffer sometimes has only half an object, the other half is still sitting in the stream waiting for the next BeginReceive call. I tried to resolve this by holding a pointer to the start of the incomplete point in the stream, set the offset in the BeginRecieve to the end of the current stream and read, ensuring I get the rest of the data, but somewhere down the line my logic screws up as I miss shed loads of messages. So...I sound like my wife, rambling on and on and on here.... I am changing it to do what you said, pass a 4 byte header which contains the length. On the asynch beginrecieve, specify 4 bytes as the size to read, then call a blocking read to read the rest, pass that off to another thread to handler the deserialise, and then start again, beginReceive for the next four byte size. I know there are loads of client servers socket examples around on CP, but you can't learn better that rolling your own from scratch, and then seeing how others have done it.
Regards Malc *********************************************