1
votes

I have written a TCP Server, in which number of bytes to read is prefixed in two-bytes header. After reading from the stream and sending the response back to the client, both NetworkStream and TcpClient are disposed. The problem is that the client doesn't seem to receive my response unless I uncomment Thread.Sleep() line. Here is the code:

using (var tcpClient = await tcpServer.AcceptTcpClientAsync())
{
    tcpClient.NoDelay = true;

    using (var stream = tcpClient.GetStream())
    {
        var twoBytesHeader = new TwoByteHeader();
        var headerBuffer = new byte[twoBytesHeader.HeaderLength];

        using (var binaryReader = new BinaryReader(stream, Encoding.ASCII, true))
        {
            headerBuffer = binaryReader.ReadBytes(twoBytesHeader.HeaderLength);

            int newOffset;
            var msgLength = twoBytesHeader.GetMessageLength(headerBuffer, 0, out newOffset);

            var buffer = binaryReader.ReadBytes(msgLength);

            string msgASCII = Encoding.ASCII.GetString(buffer);

            var bufferToSend = await ProcessMessage(msgASCII);

            using (var binaryWriter = new BinaryWriter(stream, Encoding.ASCII, true))
            {
                binaryWriter.Write(bufferToSend);
                binaryWriter.Flush();
            }

            //Thread.Sleep(1000);
        }
    }
}

When Sleep is uncommented, the client receives response and then indicates that client has disconected. I can't figure out the reason of this behaviour

1
if you need to be sure there was no error in sending your data, then async may not be the answer surely, you want to send it, know it sent, and then close? - BugFinder
Thank you for the response. In this case I am await-ing WriteAsync, so it will wait until all bytes are sent and only then close the connection. There must be something else I am doing wrong.. - GAG

1 Answers

2
votes

You are assuming that a read will read as many bytes as you specified. Instead, it will read at least one byte. Your code needs to be able to deal with that. BinaryReader.ReadBytes will allow you to read an exact number of bytes and get rid of some of your boilerplate code.

Also, you probably should not use ASCII encoding which is the worst possible encoding.