在什么条件下NetworkStream不会一次读入所有数据?

Rya*_*hel 0 c# android networkstream stream android-asynctask

在回调中,NetworkStream.BeginRead我似乎注意到始终读取所有字节。我看到许多教程检查BytesRead是否小于总字节,如果是,请再次读取,但是似乎从来没有。

if (bytesRead < totalBytes)即使一次发送大量数据(数千个字符),并且即使缓冲区大小设置为非常小的值(大约16个),该条件也永远不会触发。

我没有使用“老式方式”进行测试,因为我正在使用Task.Factory.FromAsync而不是调用NetworkStream.BeginRead并提供一个我称为EndRead的回调。也许Tasks自动包含了直到读取完所有数据才返回的功能?我不确定。

无论哪种方式,我仍然对何时不能一次读取所有数据感到好奇。甚至需要检查是否未读取所有数据,如果需要,则再次读取?我似乎无法获得有条件运行的条件。

谢谢。

Jon*_*eet 5

尝试通过慢速链接发送兆字节的数据。为什么流要等到全部出现后再给调用者任何东西?如果有什么对方没有关闭连接-那里在这一点上没有“所有数据”的概念。

假设您打开与另一台服务器的连接,并使用大缓冲区调用BeginRead(或Read),但是它仅发送100字节,然后等待您的答复-您希望NetworkStream做什么?永远不要给您数据,因为您给它提供了太大的缓冲区?那将适得其反。

绝对不应假定任何流(可争议的例外MemoryStream)将填充您提供给它的缓冲区。这可能是因为FileStream总是会为本地文件,但我希望它不是为共享文件。

编辑:示例代码,它显示未填充缓冲区-发出HTTP 1.1请求(很严重:)

// Please note: this isn't nice code, and it's not meant to be. It's just quick
// and dirty to demonstrate the point.
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;

class Test
{
    static byte[] buffer;

    static void Main(string[] arg)
    {
        TcpClient client = new TcpClient("www.yoda.arachsys.com", 80);
        NetworkStream stream = client.GetStream();

        string text = "GET / HTTP/1.1\r\nHost: yoda.arachsys.com:80\r\n" +
            "Content-Length: 0\r\n\r\n";
        byte[] bytes = Encoding.ASCII.GetBytes(text);
        stream.Write(bytes, 0, bytes.Length);
        stream.Flush();

        buffer = new byte[1024 * 1024];
        stream.BeginRead(buffer, 0, buffer.Length, ReadCallback, stream);
        Console.ReadLine();
    }

    static void ReadCallback(IAsyncResult ar)
    {
        Stream stream = (Stream) ar.AsyncState;
        int bytesRead = stream.EndRead(ar);
        Console.WriteLine(bytesRead);
        Console.WriteLine("Asynchronous read:");
        Console.WriteLine(Encoding.ASCII.GetString(buffer, 0, bytesRead));
        string text = "Bad request\r\n";
        byte[] bytes = Encoding.ASCII.GetBytes(text);
        stream.Write(bytes, 0, bytes.Length);
        stream.Flush();
        Console.WriteLine();
        Console.WriteLine("Synchronous:");

        StreamReader reader = new StreamReader(stream);
        Console.WriteLine(reader.ReadToEnd());
    }
}
Run Code Online (Sandbox Code Playgroud)