Hedimin
Hedimin

Reputation: 89

How to read and write data in tcp socket client/server

I was trying to accept some data from client, send it to the server and also send feedback from server to the client again. When server only gets some data, everething works fine. While trying to implement two-way communication, server just hungs. Server's code:

var tcpListener = new TcpListener(IPAddress.Any, 8888);
try
{
    tcpListener.Start();
    Console.WriteLine("Server is currently run, waiting for incoming connections");
    while (true)
    {
        using var tcpClient = await tcpListener.AcceptTcpClientAsync();
        await using var stream = tcpClient.GetStream();
        
        var incomeData = await DeserializeHelper.ConverteToBytes(stream);
        var incomePerson = MessagePackSerializer.Deserialize<Person>(incomeData);
        Console.WriteLine($"Income message from {incomePerson.Name}: '{incomePerson.Message}'");

        var responseMessage = $"Thank you, {incomePerson.Name} for the message";
        var responceData = MessagePackSerializer.Serialize(responseMessage);
        await stream.WriteAsync(responceData);
    }
}
finally
{
    tcpListener.Stop();
}

Client's code:

using TcpClient tcpClient = new TcpClient();
await tcpClient.ConnectAsync("127.1.199.250",8888);

Console.WriteLine("Hello, client!");

try
{
    var stream = tcpClient.GetStream();
    Console.WriteLine("Enter your name");
    var name = Console.ReadLine();
    Console.WriteLine("Enter message");
    var message = Console.ReadLine();
    Person tom = new Person(name, message);
    
    var sentData = MessagePackSerializer.Serialize(tom);
    await stream.WriteAsync(sentData);
    Console.WriteLine("Message was sent to the server");

    var incomeResponce = await DeserializeHelper.ConverteToBytes(stream);
    var incomeResponceMessage = MessagePackSerializer.Deserialize<string>(incomeResponce);
    Console.WriteLine($"Server's message: {incomeResponce}");
}
catch (Exception e)
{
    Console.WriteLine(e.Message);
}

Also all of them using my own static method ConverteToBytes, here it's code:

public static async Task<byte[]> ConverteToBytes(NetworkStream stream)
{
    await using var ms = new MemoryStream();
    byte[] bytesData = null;
    int count = 0;
    do
    {
        byte[] buffer = new byte[1024];
        count = await stream.ReadAsync(buffer,0,1024);
        ms.Write(buffer,0,count);
    } while (stream.CanRead && count > 0);
    
    return bytesData = ms.ToArray();
}

I guess the problem is with not correct stream using, but don't know what exactly is wrong. Thank's everyone!

Upvotes: 0

Views: 1244

Answers (1)

Stephen Cleary
Stephen Cleary

Reputation: 456322

I strongly recommend not using TCP/IP in the first place. If possible, use a well-established protocol with good library support, e.g., HTTP or WebSockets. Writing a correct TCP/IP application is extremely difficult.

If you must use TCP/IP, then I recommend watching my video series on the subject and reading my TCP/IP .NET Sockets FAQ.

Of particular note is that network streams are streams of bytes, not streams of messages. So there's no built-in way to know when a message completes. So you'll have to add that to your protocol yourself, i.e., using message framing. I describe message framing on my blog, and the video series linked above shows a more modern way to do it.

Without message framing, your server is likely just waiting for more bytes to arrive from the client connection.

Upvotes: 1

Related Questions