C#NetworkStream.Read()是否会等待读取指定数量的数据?

C#NetworkStream.Read()是否会等待读取指定数量的数据?,c#,networking,C#,Networking,在C/C++中,常规非阻塞网络套接字上的read()将立即返回缓冲区中当前可用的数据量,达到指定的量(因此,如果我们请求16个字节,而此时只有8个可用字节,那么我们将得到这8个字节,由我们再次调用read()并获取所有数据) 在C#中有一个NetworkStream,它具有内置超时-这是否意味着NetworkStream.Read()会等待,直到达到超时或读取请求的数据量,或者它会为我们提供缓冲区中当前可用的大于0的数据量,直到请求的数据量为止(就像标准套接字那样)即使还有时间?它也将读取参数中

在C/C++中,常规非阻塞网络套接字上的read()将立即返回缓冲区中当前可用的数据量,达到指定的量(因此,如果我们请求16个字节,而此时只有8个可用字节,那么我们将得到这8个字节,由我们再次调用read()并获取所有数据)


在C#中有一个NetworkStream,它具有内置超时-这是否意味着NetworkStream.Read()会等待,直到达到超时或读取请求的数据量,或者它会为我们提供缓冲区中当前可用的大于0的数据量,直到请求的数据量为止(就像标准套接字那样)即使还有时间?

它也将读取参数中指定字节数的可用数据,如所述,除非流通过超时或其他异常关闭

读取操作读取尽可能多的可用数据,最大读取量为size参数指定的字节数。如果远程主机关闭连接,并且已收到所有可用数据,则读取方法立即完成并返回零字节

我是这样解决的:

        byte[] TotalData = new byte[0];
        byte[] TempData = new byte[0];
        using (TcpClient TCPClient = new TcpClient())
        {
            try
            {
                TCPClient.Connect(somehost, someport);
            }
            catch (Exception eee)
            {
                // Report the connection failed in some way if necessary
            }
            if (TCPClient.Connected)
            {
                using (NetworkStream clientStream = TCPClient.GetStream())
                {
                    // You can reduce the size of the array if you know 
                    // the data received is going to be small, 
                    // don't forget to change it a little down too

                    byte[] TCPBuffer = new byte[524288];
                    int bytesRead = 0;

                    int loop = 0;
                    // Wait for data to begin coming in for up to 20 secs
                    while (!clientStream.DataAvailable && loop< 2000)
                    {
                        loop++;
                        Thread.Sleep(10);
                    }
                    // Keep reading until nothing comes for over 1 sec
                    while (clientStream.DataAvailable)
                    {
                        bytesRead = 0;

                        try
                        {
                            bytesRead = clientStream.Read(TCPBuffer, 0, 524288);
                            Array.Resize(ref TempData, bytesRead);
                            Array.Copy(TCPBuffer, TempData, bytesRead);
                            // Add data to TotalData
                            TotalData = JoinArrays(TotalData, TempData);
                        }
                        catch
                        {
                            break;
                        }

                        if (bytesRead == 0)
                            break;

                        Thread.Sleep(1000);
                    }
                }
            }
        }

安全的方法是使用MemoryStream,它将确保等待并将所有流读取到内存中,然后您可以随意使用它

     public void SaveUserTemplate(Stream stream)
     {
        MemoryStream memoryStream = new MemoryStream();
        stream.CopyTo(memoryStream);
        memoryStream.Position = 0;

      
        byte[] templatePathLength = new byte[4];
        memoryStream.Read(templatePathLength, 0, templatePathLength.Length);
        int nBytesTemplatePathLength = BitConverter.ToInt32(templatePathLength,0);

        ....
CopyTo函数最后调用此函数:


但是,如果仍然有时间(从调用stream.read() public void SaveUserTemplate(Stream stream) { MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); memoryStream.Position = 0; byte[] templatePathLength = new byte[4]; memoryStream.Read(templatePathLength, 0, templatePathLength.Length); int nBytesTemplatePathLength = BitConverter.ToInt32(templatePathLength,0); ....
private void InternalCopyTo(Stream destination, int bufferSize)
    {
        Contract.Requires(destination != null);
        Contract.Requires(CanRead);
        Contract.Requires(destination.CanWrite);
        Contract.Requires(bufferSize > 0);
        
        byte[] buffer = new byte[bufferSize];
        int read;
        while ((read = Read(buffer, 0, buffer.Length)) != 0)
            destination.Write(buffer, 0, read);
    }