【问题标题】:NetworkStream BeginRead only reads once?NetworkStream BeginRead 只读取一次?
【发布时间】:2011-08-24 11:14:22
【问题描述】:

我有一些非常简单的代码,可以从它连接的网络流中读取行。在代码示例中,每次读取只有一行,并且不会继续从服务器获取更多内容。

怎么了?

        byte[] readBuffer = new byte[1024];
        byte[] tempBuff = new byte[1024];
        int tempBuffSize = 0;    


private void btnConnect_Click(object sender, EventArgs e)
            {

            TcpClient tcpClient = new TcpClient("192.168.1.151", 5505);
            NetworkStream stream = tcpClient.GetStream();
            stream.BeginRead(readBuffer, 0, 1024, readHandler, tcpClient); 
        }

void readHandler(IAsyncResult result)
        {
            TcpClient tcpClient = (TcpClient)result.AsyncState;
            int dataLen = tcpClient.GetStream().EndRead(result);

            int currStart = 0;
            int currEnd = -1;

            for (int i = 0; i < dataLen; i++)
            {
                if (readBuffer[i] == '\r' && i < (readBuffer.Length - 1) &&
                    readBuffer[i + 1] == '\n')
                {
                    // Set the end of the data 
                    currEnd = i - 1;

                    // If we have left overs from previous runs: 
                    if (tempBuffSize != 0)
                    {

                        byte[] joinedData = new byte[tempBuffSize + (currEnd - currStart + 1)];
                        Array.Copy(tempBuff, 0, joinedData, 0, tempBuffSize);
                        Array.Copy(readBuffer, currStart, joinedData, tempBuffSize, (currEnd - currStart + 1));

                        System.Text.Encoding enc = System.Text.Encoding.ASCII;
                        string myString = enc.GetString(joinedData);
                        System.Diagnostics.Debug.Write(myString);

                        tempBuffSize = 0;
                    }
                    else
                    {
                        System.Text.Encoding enc = System.Text.Encoding.ASCII;
                        string myString = enc.GetString(readBuffer);
                        System.Diagnostics.Debug.Write(myString);

                        // HandleData(readBuffer, currStart, currEnd);
                    }

                    // Set the new start - after our delimiter 
                    currStart = i + 2;
                }

            }

            // See if we still have any leftovers 
            if (currStart < dataLen)
            {
                Array.Copy(readBuffer, currStart, tempBuff, 0, dataLen - currStart);
                tempBuffSize = dataLen - currStart;
            }
        }  

【问题讨论】:

  • 您应该阅读如何从网络获取数据。网络编程的问题在于,您无法保证当服务器向您发送 1000 字节时,您会以 1000 字节的形式接收它,您可能会以 100 字节的桶的形式接收它,或者先是 300,然后是 600,然后是 100 字节。那都是“随机的”。因此,您应该继续从流中读取,直到获得所需的所有数据。通常,这是通过再次调用 BeginRead 来结束 readHandler 来完成的(从而形成某种异步循环)。
  • 以上评论应该是一个答案(除了它实际上与我的答案相同)。

标签: c# networkstream


【解决方案1】:

您为什么希望它首先读取整个信息?我不是专家,但在我看来,同步和异步方法都不能保证读取所有数据(无论这意味着什么,因为只要打开套接字,就有更多数据可以到达)。在 EndRead 方法中的代码之后,如果您需要更多数据,您应该再次调用 Read 或 BeginRead。根据您与客户端建立的协议,您应该知道是否需要更多数据。

【讨论】:

    【解决方案2】:

    我在为嵌入式设备开发 tcp 应用程序时遇到了类似的问题。在我的情况下,问题是设备在延迟时间内发出数据,因此在其余数据可以进入之前,控件移动到程序中的下一行,仅从服务器获取初始数据。我通过引入延迟解决了这个问题。

    就在您从服务器读取数据的行之后会引入延迟,因此最好在单独的线程上运行它

    thread.sleep(3000)
    

    这很可能是你的问题。

    【讨论】:

      【解决方案3】:

      也许你的流对象在它超出范围时被释放,在 readHandler 可以再次被调用之前。尝试将 tcpClient 和流提升到类范围而不是方法范围,或者将读取移动到操作完成时退出的单独线程。

      【讨论】:

      • 不,我只是将流和 tcpClient 移到类范围内,没有任何变化:-(
      猜你喜欢
      • 2011-05-22
      • 1970-01-01
      • 1970-01-01
      • 2015-11-09
      • 1970-01-01
      • 2011-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多