简体   繁体   中英

TcpListener and NetworkStream doesn't get data

I am trying to receive a message from an equipment. This equipment is an authentication terminal, and it will send the message as soon as the user set his credentials.

Also, the manual of the equipment says the message will be sent in the ILV format, standing I for identification, L for length and V for value.

a normal message would be:

I -> 0x00 (byte 0 indicating success)
L -> 0x04 0x00 (two bytes for length, being 4 the length in this case)
V -> 0x35 0x32 0x38 0x36 (the message itself)

The message is sent in TCP protocol, so I created a socket using the TcpListener class, following this sample from Microsoft:

https://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener(v=vs.110).aspx

new Thread(() =>
        {
            TcpListener server = null;
            try
            {
                Int32 port = 11020;
                IPAddress localAddr = IPAddress.Parse("192.168.2.2");

                server = new TcpListener(localAddr, port);
                server.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

                server.Start();

                byte[] bytes = new byte[256];
                String data = null;

                while (true)
                {
                    TcpClient client = server.AcceptTcpClient();
                    data = null;

                    NetworkStream stream = client.GetStream();

                    int i = 0;

                    while((i = stream.Read(bytes, 0, bytes.Length)) != 0)
                    {
                        // this code is never reached as the stream.Read above runs for a while and receive nothing
                        data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
                    }

                    client.Close();
                }
            }
            catch (SocketException ex)
            {
                // Actions for exceptions.
            }
            finally
            {
                server.Stop();
            }
        }).Start();

If the stream.Read is removed, then the code flows (although I got nothing either), however if I put any stream.Read statement the execution holds for a while like it was waiting for some response, and then it ends with no response, all bytes read is zero.

I am running Wireshark on the computer and the data is being sent.

Anybody knows what I am doing wrong?

I think the problem is right in the Read method, which halts until the buffer fills completely, but that's obviously won't happen anytime.

In that while -loop, you should spin by checking for available data first, then read them and append to the byte-array. Moreover, since the loop become too "tight", it's better to yield the control to the task scheduler for a bit.

Here is an example:

while (true)
{
    if (stream.DataAvailable)
    {
        int count = stream.Read(bytes, i, bytes.Length);
        i += count;
        // ...add something to detect the end of message
    }
    else
    {
        Thread.Sleep(0);
    }
}

It's worthwhile to notice that there's no timeout, but that's a very common feature in order to quit the loop when no data (or broken) are incoming.

Furthermore, the above pattern is not the best way to accumulate data, because you may get an exception when too many bytes are received. Consider a spurious stream of 300 bytes: that will overflow the available buffer. Either use the "bytes" as a temporary buffer for what the Read method gives, or provide a safety check before calling the Read method (so that you may provide the best byte count to read).

Useful links here:

https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.networkstream.read?view=netframework-4.7.1#System_Net_Sockets_NetworkStream_Read_System_Byte___System_Int32_System_Int32_

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM