0

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.

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|" and I was able to split it and process it in a foreach loop.

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?

Community
  • 1
  • 1
Jannik
  • 2,310
  • 6
  • 32
  • 61
  • What's wrong with the solution you've got at the moment? Using a predetermined delimiter seems perfectly fine to me. – James Feb 02 '14 at 11:56
  • 1
    Nothing wrong with it. Just curious, if there's a better way. What implemtation do you use to split them after receiving both objects? – Jannik Feb 02 '14 at 11:58
  • Here is an example that uses newline as separator http://stackoverflow.com/questions/12721710/serialized-data-on-tcpclient-needs-to-state-amount – L.B Feb 02 '14 at 12:01

1 Answers1

2

Here is a generic example to send objects between client and server using Json.Net. It uses NewLine char as separator. So All you need is to create StreamReader and StreamWriter from network streams and to use ReadLine and WriteLine methods....

(PS: Since Json.Net escapes NewLine char in serialization, messages containing it doesn't cause problems...)

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();
});
I4V
  • 34,891
  • 6
  • 67
  • 79