0
\$\begingroup\$

Here is an async Tcp server using async/await I have written. I would be very appreciate if anyone can help to improve my code. Thank you!

public class TcpServer
{
    private int DefaultPort = 6340;
    public TcpListener TcpListener { get; set; }

    public TcpServer()
    {
        var ip = NetworkHelper.GetLocalIPAddress();
        var idAddress = IPAddress.Parse(ip as string);
        TcpListener = new TcpListener(idAddress, DefaultPort );

        ReceiveDataAsync();
    }

    private async void ReceiveDataAsync()
    {
        try
        {
            TcpListener.Start();
            while (true)
            {
                var tcpClient = await TcpListener.AcceptTcpClientAsync();
                ReadDataFromClientAsync(tcpClient);
            }
        }
        catch (Exception e)
        {
            // To Log;
        }
    }

    private async void ReadDataFromClientAsync(TcpClient client)
    {
        try
        {
            var stream = client.GetStream();
            while (client.Connected)
            {
                List<byte> totalBytes = new List<byte>();
                // The first 4 bytes record the length of the code.
                var countBytes = new byte[4];
                var count = await stream.ReadAsync(countBytes, 0, countBytes.Length);
                // use this to detect if tcp client is connected.
                if (count == 0)
                {
                    break;
                }
                var size = BitConverter.ToInt32(countBytes, 0);
                while (size > 0)
                {
                    byte[] bytes;
                    if (size < 256)
                    {
                        bytes = new byte[size];
                    }
                    else
                    {
                        bytes = new byte[256];
                    }
                    var byteCount = await stream.ReadAsync(bytes, 0, bytes.Length);
                    totalBytes.AddRange(bytes);
                    size -= 256;
                }
                var message = Encoding.Default.GetString(totalBytes.ToArray(), 0, totalBytes.Count);

                // Do some logic using the message....

            }
            client.Close();
        }
        catch (IOException e)
        {
            client.Close();
        }
    }
}
\$\endgroup\$
4
  • \$\begingroup\$ Why is TcpListener a public get/set property instead of a private readonly field? \$\endgroup\$
    – Sam
    Commented Apr 13, 2016 at 5:29
  • \$\begingroup\$ idAddress is presumably a typo \$\endgroup\$
    – Sam
    Commented Apr 13, 2016 at 5:29
  • \$\begingroup\$ async void doesn't work. It should be async Task. haacked.com/archive/2014/11/11/async-void-methods \$\endgroup\$
    – Sam
    Commented Apr 13, 2016 at 5:31
  • \$\begingroup\$ @Sam, but I don't need to await for that, I just need the function return right after it is called, do I still need async Task? Maybe async void is not a good choice but it seems async Task not change anything. \$\endgroup\$
    – Man Shen
    Commented Apr 17, 2016 at 6:55

1 Answer 1

3
\$\begingroup\$

Just a very quick note: you really don't want to be using Encoding.Default for messages passed between different computers! If the other computer uses a different encoding your message will be garbage.

Take a look at the msdn docs:

Different computers can use different encodings as the default, and the default encoding can even change on a single computer. Therefore, data streamed from one computer to another or even retrieved at different times on the same computer might be translated incorrectly. In addition, the encoding returned by the Default property uses best-fit fallback to map unsupported characters to characters supported by the code page. For these two reasons, using the default encoding is generally not recommended. To ensure that encoded bytes are decoded properly, you should use a Unicode encoding, such as UTF8Encoding or UnicodeEncoding, with a preamble. Another option is to use a higher-level protocol to ensure that the same format is used for encoding and decoding.

(My emphasis)

You can read about best fit fallback here: Character Encoding in the .NET Framework.

This is generally the canonical link for an introduction to character encoding (and why unicode): The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!).

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.