简体   繁体   English

C#TcpClient:使用分隔符发送序列化对象?

[英]C# TcpClient: Send serialized objects using separators?

Based on serialization (mentioned here https://stackoverflow.com/a/7849374/985798 ) I am trying to reengineer my small tcp application, which was using a string message until now. 基于序列化(在这里提到https://stackoverflow.com/a/7849374/985798 ),我正在尝试重新设计我的小型tcp应用程序,该应用程序迄今仍在使用字符串消息。

But I ran into a small problem and I would like to know what solution you'd recommend me to use: 但是我遇到了一个小问题,我想知道您建议我使用哪种解决方案:

If I am trying to send more than one message in a very small interval, they will be merged in the "queue" and the client will receive both messages at the same time, which will end up with a single broken object. 如果我试图在很小的时间间隔内发送多个消息,则它们将被合并到“队列”中,客户端将同时接收到这两个消息,最终将导致单个损坏的对象。 In the past I solved this problem with a string separator "|end|" 过去,我使用字符串分隔符“ | end |”解决了这个问题 and I was able to split it and process it in a foreach loop. 我能够将其拆分并在foreach循环中进行处理。

Is that a good approach? 那是一个好方法吗? How would you solve that problem based on serialized object byte arrays? 您如何基于序列化的对象字节数组解决该问题? Would you use a byte[] delimiter or use another solution? 您将使用byte[]分隔符还是使用其他解决方案?

Here is a generic example to send objects between client and server using Json.Net. 这是一个使用Json.Net在客户端和服务器之间发送对象的通用示例。 It uses NewLine char as separator. 它使用NewLine char作为分隔符。 So All you need is to create StreamReader and StreamWriter from network streams and to use ReadLine and WriteLine methods.... 因此,您所需要做的就是从网络流创建StreamReader和StreamWriter并使用ReadLine和WriteLine方法。

(PS: Since Json.Net escapes NewLine char in serialization, messages containing it doesn't cause problems...) (PS:由于Json.Net在序列化中转义了NewLine char,因此包含它的消息不会引起问题...)

void SendObject<T>(StreamWriter s, T o)
{
    s.WriteLine( JsonConvert.SerializeObject(o) );
    s.Flush();
}

T ReadObject<T>(StreamReader r)
{
    var line = r.ReadLine();
    if (line == null) return default(T);
    return JsonConvert.DeserializeObject<T>(line);
}

SemaphoreSlim serverReady = new SemaphoreSlim(0);
//SERVER
Task.Factory.StartNew(() =>
    {
        TcpListener listener = new TcpListener(IPAddress.Any, 8088);
        listener.Start();
        serverReady.Release();
        while(true)
        {
            var client = listener.AcceptTcpClient();
            Task.Factory.StartNew(() =>
                {
                    Console.WriteLine("Client connected...");
                    var reader = new StreamReader(client.GetStream());
                    var obj = ReadObject<string>( reader) ;
                    while(obj != null)
                    {
                        Console.WriteLine("[" + obj + "]");
                        obj = ReadObject<string>(reader);
                    }
                    Console.WriteLine("Client disconnected...");
                });
        }

    });


serverReady.Wait();
//CLIENT
Task.Factory.StartNew(() =>
{
    TcpClient client = new TcpClient();
    client.Connect("localhost", 8088);
    var writer = new StreamWriter(client.GetStream());
    for (int i = 0; i < 10; i++)
    {
        SendObject(writer, "test\nmessage" + i); //message containing `\n` :)
    }
    client.Close();
});

You shouldn't even need a delimiter in your case, all you are trying to do here is pass an object in chunks. 在这种情况下,您甚至都不需要定界符,您在这里要做的就是将对象分块传递。 I would recommend going for something a little lighter than XML serialization eg JSON. 我建议比XML序列化(例如JSON)轻一些。

var objectJson = new JavaScriptSerializer().Serialize(myObject);

This would give you a string in the format of 这将为您提供以下格式的字符串

{
    "Member1": "Value",
    "Member2": [ "Value1", "Value2" ],
    ...etc
}

All you need to do is keep merging the chunks until you have a complete object then call 您需要做的就是不断合并这些块,直到您拥有一个完整的对象,然后调用

var object = new JavaScriptSerializer().Deserialize<MyObject>(objectJson);

On the other side. 另一方面。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM