Search code examples
c#asp.net-coretcpasync-awaitnetworkstream

TCP write and read commands give different results when I put breakpoints


I want to get a weight from a scale in C# so I'm using a TCP connection for that.

This is my code,

private TcpClient _client;
public NetworkStream Stream { get; private set; }

public ScalesService()
{
    _client = new TcpClient();
}

async public Task<string> TestRead()
{
    var responseLength = 1024;
    var readResponse = new byte[responseLength];

    string result = "";

    Console.WriteLine("connecting...");
    await _client.ConnectAsync("10.100.200.70", 1182);
    Console.WriteLine("connected!");

    Stream = _client.GetStream();

    var cmdUser = Encoding.ASCII.GetBytes("user admin\n");
    await Stream.WriteAsync(cmdUser, 0, cmdUser.Length);

    var countCmdUser = await Stream.ReadAsync(readResponse, 0, readResponse.Length);
    var responseCmdUser = Encoding.ASCII.GetString(readResponse, 0, countCmdUser);

    var cmdRead = Encoding.ASCII.GetBytes("read wt0501\n");

    await Stream.WriteAsync(cmdRead, 0, cmdRead.Length);

    var countCmdRead = await Stream.ReadAsync(readResponse, 0, readResponse.Length);
    var responseCmdRead = Encoding.ASCII.GetString(readResponse, 0, countCmdRead);

    //result = responseCmdRead;

    if (!string.IsNullOrEmpty(responseCmdRead))
    {
        // Expected Return: [00R001~       10300~]
        var responseArray = responseCmdRead.Split('~');
        if (responseArray.Length >= 2)
        {
            var weightString = responseArray[1];

            float grossNetWt;
            result = weightString;
            //if (float.TryParse(weightString, out grossNetWt))
            //{
            //    result = grossNetWt;
            //}
        }
    }

    var cmdQuit = Encoding.ASCII.GetBytes("quit\n");
    await Stream.WriteAsync(cmdQuit, 0, cmdQuit.Length);

    return result;
}

It seems like the stream doesn't wait to send me the full answer. I got different results when I put breakpoints or not. Is there a better way to do that? I was thinking that the await would be a good solution.


Solution

  • As noted in the comment, TCP/IP sockets are streams of bytes, not packets. If you want to read/write an entire message, you need to use some kind of message framing.

    Since you already have a device, the type of message framing should be documented in the device's protocol specification. From the example code you posted, it looks like it's using a message delimiter of \n. So you'll need to have a read loop that adds bytes to a buffer until you see the \n.