Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Serialisation of more than one object

Serialisation of more than one object

Scheduled Pinned Locked Moved C#
sysadmindata-structuresquestion
4 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Malcolm Smart
    wrote on last edited by
    #1

    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

    M 1 Reply Last reply
    0
    • M Malcolm Smart

      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

      M Offline
      M Offline
      Malcolm Smart
      wrote on last edited by
      #2

      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 *********************************************

      H 1 Reply Last reply
      0
      • M Malcolm Smart

        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 *********************************************

        H Offline
        H Offline
        HellfireHD
        wrote on last edited by
        #3

        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.

        M 1 Reply Last reply
        0
        • H HellfireHD

          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.

          M Offline
          M Offline
          Malcolm Smart
          wrote on last edited by
          #4

          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 *********************************************

          1 Reply Last reply
          0
          Reply
          • Reply as topic
          Log in to reply
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes


          • Login

          • Don't have an account? Register

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • World
          • Users
          • Groups