如何在C#中跨网络发送任意对象

时间:2019-06-28 09:49:56

标签: c# json sockets serialization

我正在尝试使用C#中的套接字在网络上发送任意对象。

我已经习惯Java及其工作原理,这是C#的新手。 在Java中,我可以创建一个Socket,创建一个OutputObjectStream,然后仅发送对象。我不需要担心序列化。

另一方面,我还有一个套接字,创建一个ObjectInputStream,读取对象,然后将其转换回原始类型。

Java示例:

ObjectInputStream inFromClient = new ObjectInputStream (socket.getInputStream());
Object read = inFromClient.readObject();
if(read instanceof bool) {
    // cast read to bool, and call relevant method
} else if(read instanceof UserInfo) {
    // cast read to UserInfo...
} else if(read instanceof CarInfo) {
    // cast read to CarInfo...
}

但是在C#(我正在使用JSON)中,据我所知,我需要先将Object转换为JSON,然后转换为byte [],然后将其发送。另一方面,我从byte []转换为字符串,然后转换为JSON。我使用DataContractJsonSerializer,它需要知道我希望再次退出哪个对象。但是我没有这些信息。

我当前的解决方案是每次发送两次。发送的第一个对象是方法名称(表示为枚举),发送的第二个对象是实际对象。基于第一个收到的方法名称,我知道第二个对象应该是什么,并且可以将此告知我的JSON序列化程序包装器。像这样:

public static T FromJSON<T>(string json) {
var ms1 = new MemoryStream(Encoding.ASCII.GetBytes(json));
DataContractJsonSerializer dataContractJsonSerializer = new DataContractJsonSerializer(typeof(T));
T sm1 = (T) dataContractJsonSerializer.ReadObject(ms1);
return  sm1;

我可能可以优化一点,并创建一个包装类,例如SocketMessage,它将保存枚举方法名称,以及一个string类型的参数来保存JSON字符串。但这真的是这样做的方法吗?

是否没有像Java那样的“简单”解决方案?

不一定是套接字,但这就是我所熟悉的。我只需要一台运行服务器的计算机,然后在它旁边的一台计算机运行客户端,因此可以使用套接字以外的其他方法。他们将位于同一网络上,所以我认为没有花哨的Webstuff。我需要一个开放的双向连接。

2 个答案:

答案 0 :(得分:2)

您可以做一些事情来简化此操作:

  • 将套接字包装在NetworkStream中。这样一来,您就可以在流中进行读/写操作,并使序列化的界面更容易一些。
  • 使用Newtonsoft.Json将对象与json序列化。我发现它比DataContractSerializer更易于使用。另外,您可以:
  • 在您的序列化对象中包括类型信息。当您使用Newtonsoft.Json时,如果序列化中包含类型信息,则在反序列化时无需事先知道类型。为此,例如,将TypeNameHandling设置为TypeNameHandling.Object。 (出于安全考虑,您不应该使用它在网络外进行通信)

将它们放在一起:

// 'client' side
using (var socket = new Socket(SocketType.Stream, ProtocolType.IPv6))
using (var networkStream = new NetworkStream(socket))
using (var writer = new StreamWriter(networkStream))
using (var jsonWriter = new JsonTextWriter(writer)) 
{
    socket.Connect("localhost", 8888);
    var user = new UserInfo { Name = "Jesse de Wit" }; // That's me
    var settings = new JsonSerializerSettings()
    {
        TypeNameHandling = TypeNameHandling.Objects
    };
    var serializer = JsonSerializer.Create(settings);
    serializer.Serialize(jsonWriter, user);
}

// 'server' side
using (var socket = new Socket(SocketType.Stream, ProtocolType.IPv6))
using (var networkStream = new NetworkStream(socket))
using (var reader = new StreamReader(networkStream))
using (var jsonReader = new JsonTextReader(reader))
{
    socket.Accept();
    var settings = new JsonSerializerSettings()
    {
        TypeNameHandling = TypeNameHandling.Objects
    };
    var serializer = JsonSerializer.Create(settings);

    // Note that obj will be a JObject if no type information is included.
    object obj = serializer.Deserialize(jsonReader);
    if (obj is UserInfo user)
    {
        // Jesse de Wit 
        Console.WriteLine(user.Name);
    }
}

答案 1 :(得分:0)

通过使用newtonsoft库,在c#中通过JSon Parse甚至可以在{#1}}中使用dynamic,因此可以按原样对字符串进行序列化,另一方面,您可能可以理解类型是通过查看对象的关键属性来实现的。