tags:

views:

139

answers:

3

I have a client server application in which I need to transmit a user defined object from Client to Server using TCP connection. My object is of the following structure:

class Conversation
{
    private string convName, convOwner;
    public ArrayList convUsers;

    public string getConvName()
    {
       return this.convName;
    }
    public string getConvOwner()
    {
       return this.convOwner;
    }
}

Please help me how to transmit this object at from client and again de-serialize it into appropriate object at server side.

+2  A: 

You need to make your object serializable.

Brian R. Bondy
the fundamental thing!
TheVillageIdiot
+4  A: 

One good course of action is to expose this object as a DataContract to a framework like WCF, and use the appropriate transports available in that framework.

For example:

[DataContract]
class Conversation
{
    private string convName, convOwner;
    public ArrayList convUsers;

    [DataMember]
    public string ConvName
    {
       get { return this.convName; }
    }
    [DataMember]
    public string ConvOwner
    {
       get { return this.convOwner; }
    }
}
Jeff Meatball Yang
+1 By far the simplest way to achieve the required result: serialization is out-of-the-box, and configuration of the transport takes minutes.
Kirk Broadhurst
+1 for using properties rather than accessor methods.
Dour High Arch
A: 

As answered, you should make your object serializable. Once you did that with the Serializable attribute, you can use the famous BinaryFormatter to convert your object into a byte array.

You can find many examples out there for using the BinaryFormatter, just use your favorite search engine. Here's a short example:

using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

public class SerializationUtils
{
    public static byte[] SerializeToByteArray(object request)
    {
        byte[] result;
        BinaryFormatter serializer = new BinaryFormatter();
        using (MemoryStream memStream = new MemoryStream())
        {
            serializer.Serialize(memStream, request);
            result = memStream.GetBuffer();
        }
        return result;
    }

    public static T DeserializeFromByteArray<T>(byte[] buffer)
    {
        BinaryFormatter deserializer = new BinaryFormatter();
        using (MemoryStream memStream = new MemoryStream(buffer))
        {
            object newobj = deserializer.Deserialize(memStream);
            return (T)newobj;
        }
    }
}

As for your class, it includes two private fields. I can't see where you set values for them, so I changed your code a bit, so that they can be set in the constructor. In addition, I added the needed Serializable attribute:

using System;
using System.Collections;

[Serializable]
public class Conversation
{
    public Conversation(string convName, string convOwner)
    {
        this.convName = convName;
        this.convOwner = convOwner;
    }

    public Conversation()
    {
    }

    private string convName, convOwner;
    public ArrayList convUsers;

    public string getConvName()
    {
        return this.convName;
    }
    public string getConvOwner()
    {
        return this.convOwner;
    }
}

Now let's put it all together, and see your class serialized and then deserialized, in a Console Application:

using System;
using System.Collections;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace Capishi
{
    [Serializable]
    public class Conversation
    {
        public Conversation(string convName, string convOwner)
        {
            this.convName = convName;
            this.convOwner = convOwner;
        }

        public Conversation()
        {
        }

        private string convName, convOwner;
        public ArrayList convUsers;

        public string getConvName()
        {
            return this.convName;
        }
        public string getConvOwner()
        {
            return this.convOwner;
        }
    }

    public class SerializationUtils
    {
        public static byte[] SerializeToByteArray(object request)
        {
            byte[] result;
            BinaryFormatter serializer = new BinaryFormatter();
            using (MemoryStream memStream = new MemoryStream())
            {
                serializer.Serialize(memStream, request);
                result = memStream.GetBuffer();
            }
            return result;
        }

        public static T DeserializeFromByteArray<T>(byte[] buffer)
        {
            BinaryFormatter deserializer = new BinaryFormatter();
            using (MemoryStream memStream = new MemoryStream(buffer))
            {
                object newobj = deserializer.Deserialize(memStream);
                return (T)newobj;
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // create and initialize a conversation object
            var convName = "Capishi";
            var convOwner = "Ice Cream";
            Conversation myConversation = new Conversation(convName, convOwner);
            myConversation.convUsers = new ArrayList();
            myConversation.convUsers.Add("Ron Klein");
            myConversation.convUsers.Add("Rakesh K");

            // serialize to a byte array
            byte[] data = SerializationUtils.SerializeToByteArray(myConversation);

            // print the resulting byte array if you want
            // PrintArray(data);

            // deserialize the object (on the other side of the communication
            Conversation otherConversation = SerializationUtils.DeserializeFromByteArray<Conversation>(data);

            // let's see if all of the members are really there
            Console.WriteLine("*** start output ***");
            Console.WriteLine("otherConversation.getConvName() = " + otherConversation.getConvName());
            Console.WriteLine("otherConversation.getConvOwner() = " + otherConversation.getConvOwner());
            Console.WriteLine("otherConversation.convUsers:");
            foreach (object item in otherConversation.convUsers)
            {
                Console.WriteLine(item);
            }
            Console.WriteLine("*** done output ***");

            // wait before close
            Console.ReadLine();

        }

        /// <summary>
        /// just a helper function to dump an array to the console's output
        /// </summary>
        /// <param name="data"></param>
        private static void PrintArray(byte[] data)
        {
            for (int i = 0; i < data.Length; i++)
            {
                Console.Write("{0:000}", data[i]);
                if (i < data.Length - 1)
                    Console.Write(", ");
            }
            Console.WriteLine();
        }
    }
}

The result is:

*** start output ***
otherConversation.getConvName() = Capishi
otherConversation.getConvOwner() = Ice Cream
otherConversation.convUsers:
Ron Klein
Rakesh K
*** done output ***

And a final note:

I'd use the generic List instead of the outdated ArrayList, unless you're bound to .NET 1.*.

Ron Klein
Hey Ron, thanks for the help. BUt I am getting the following exception when I try to run this in my program: System.Runtime.Serialization.SerializationException was unhandled Message="Unable to find assembly 'TCPCustomObjectClient, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'." where TCPCustomObjectClient is my program that serializes the object and sends it over the network.I am not able to understand this exception. COuld you please clarify?
Rakesh K
@Rakesh, you should have a reference to the assembly that has the `Conversation` class in the other side, too.
Ron Klein
@Ron, Thanks!!! I added the class declaration for Conversation in a DLL and referenced it from both the sides, and it is perfectly working. Thanks again!!!
Rakesh K
The binary serialization format is runtime-dependent, I would not recommend using it for persistent or remote interprocess communication. Use XML or DataContract serialization. Also, using public accessor methods to private fields and publicly exposing collection backing stores is highly non-idiomatic.
Dour High Arch