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.
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?
Solution 1:
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();
});