2010-04-12 6 views
3

У меня есть клиентское серверное приложение, в котором мне нужно передать определенный пользователем объект от клиента к серверу, используя TCP-соединение. Мой объект имеет следующую структуру:Передача сложных объектов с использованием TCP

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

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

Пожалуйста, помогите мне, как передать этот объект в количестве от клиента и снова десериализации его в соответствующий объект на стороне сервера.

ответ

4

Как ответили, вы должны сделать свой объект сериализации. Как только вы сделали это с атрибутом Serializable, вы можете использовать знаменитый BinaryFormatter, чтобы преобразовать ваш объект в массив byte.

Вы можете найти множество примеров для использования BinaryFormatter, просто используйте свою любимую поисковую систему. Вот краткий пример:

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; 
     } 
    } 
} 

Что касается вашего класса, она включает в себя два частных поля. Я не вижу, где вы установили для них значения, поэтому я немного изменил код, чтобы их можно было установить в конструкторе. Кроме того, я добавил необходимый Serializable атрибут:

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; 
    } 
} 

Теперь давайте соберем все вместе, и увидеть свой класс сериализуется, а затем десериализации, в консольном приложении:

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(); 
     } 
    } 
} 

Результат является:

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

И последнее примечание:

Я бы использовал общий List вместо устаревшего ArrayList, если только вы не связаны с .NET 1. *.

+0

Эй, Рон, спасибо за помощь. BUt Я получаю следующее исключение, когда я пытаюсь запустить это в своей программе: System.Runtime.Serialization.SerializationException был необработанным Message = «Не удалось найти сборку» TCPCustomObjectClient, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null ' «. где TCPCustomObjectClient - это моя программа, которая сериализует объект и отправляет его по сети. Я не могу понять это исключение. Объясните пожалуйста, уточните? –

+0

@ Rakesh, вы должны иметь ссылку на сборку, которая имеет класс «Разговор» на другой стороне. –

+0

Спасибо !!! Я добавил объявление класса для беседы в DLL и ссылался на него с обеих сторон, и он отлично работает. Еще раз спасибо!!! –

4

Один хороший курс действий заключается в том, чтобы обнародовать этот объект как DataContract на фреймворк, такой как WCF, и использовать appropriate transports, доступный в этой структуре.

Например:

[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; } 
    } 
} 
+0

+1 На сегодняшний день самый простой способ добиться требуемого результата: сериализация является готовой, а конфигурация транспорта занимает несколько минут. –

Смежные вопросы