【问题标题】:TcpListener and NetworkStream doesn't get dataTcpListener 和 NetworkStream 不获取数据
【发布时间】:2018-08-26 22:58:46
【问题描述】:

我正在尝试接收来自设备的消息。本设备为鉴权终端,用户设置凭据后立即发送消息。

另外,设备说明书上说信息会以ILV格式发送,代表I代表标识,L代表长度,V代表价值。

正常的消息是:

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)

消息是在 TCP 协议中发送的,所以我使用 TcpListener 类创建了一个套接字,遵循 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();

如果 stream.Read 被删除,那么代码就会流动(虽然我什么也没有得到),但是如果我放置任何 stream.Read 语句,执行会持续一段时间,就像它在等待某个响应一样,然后它结束没有响应,读取的所有字节都为零。

我正在计算机上运行 Wireshark,并且正在发送数据。

有人知道我做错了什么吗?

【问题讨论】:

    标签: c# sockets


    【解决方案1】:

    我认为问题出在Read 方法中,该方法会停止直到缓冲区完全填满,但这显然不会随时发生。

    在那个while-loop 中,您应该首先检查可用数据,然后读取它们并附加到字节数组中。此外,由于循环变得太“紧”,最好将控制权交给任务调度程序。

    这是一个例子:

    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);
        }
    }
    

    值得注意的是,没有超时,但这是一个非常常见的功能,以便在没有数据(或损坏)传入时退出循环。

    此外,上述模式不是累积数据的最佳方式,因为当接收到的字节数过多时,您可能会遇到异常。考虑一个 300 字节的虚假流:这将溢出可用缓冲区。使用“字节”作为Read 方法提供的临时缓冲区,或者在调用Read 方法之前提供安全检查(以便您可以提供最佳字节数来读取)。

    这里有用的链接:

    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_

    【讨论】:

    • 数据永远不可用 =/
    • CanRead 属性为真。可能是客户端问题?
    • 是的,这是客户端问题。您的解决方案帮助我意识到这一点。谢谢你:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-09
    • 2019-01-19
    • 2014-11-21
    • 1970-01-01
    • 1970-01-01
    • 2020-07-26
    • 1970-01-01
    相关资源
    最近更新 更多