C# 在什么情况下NetworkStream不能同时读取所有数据?
在NetworkStream.BeginRead的回调中,我似乎注意到所有字节总是被读取的。我看到许多教程检查字节读取是否小于总字节数,如果是,请重新读取,但情况似乎从未如此 如果(bytesReadC# 在什么情况下NetworkStream不能同时读取所有数据?,c#,android,stream,android-asynctask,networkstream,C#,Android,Stream,Android Asynctask,Networkstream,在NetworkStream.BeginRead的回调中,我似乎注意到所有字节总是被读取的。我看到许多教程检查字节读取是否小于总字节数,如果是,请重新读取,但情况似乎从未如此 如果(bytesRead
if(bytesRead
永远不会触发,即使一次发送大量数据(数千个字符),并且即使缓冲区大小设置为非常小的值(16个左右)
我没有用“老式的方法”对此进行测试,因为我使用Task.Factory.fromsync而不是调用NetworkStream.beginhead,并提供了一个回调,在那里我调用EndRead。也许任务自动包含在读取所有数据之前不返回的功能?我不确定
不管是哪种方式,我仍然很好奇什么时候所有的数据都不会被一次读取。是否需要检查是否未读取所有数据,如果是,则再次读取?我似乎永远也无法让这个条件运行
谢谢。尝试通过慢速链接发送兆字节的数据。为什么流要等到它全部存在之后再给调用者任何一个呢?如果另一方没有关闭连接怎么办?在这一点上没有“所有数据”的概念 假设您打开与另一台服务器的连接并使用大缓冲区调用
BeginRead
(或Read
),但它只发送100个字节,然后等待您的答复-您希望NetworkStream
做什么?永远不要给你数据,因为你给了它太大的缓冲区?这将产生严重的反作用
您绝对不应该假设任何流(除了MemoryStream
)将填充您提供的缓冲区。对于本地文件,FileStream
可能总是这样,但对于共享文件,我希望不是这样
编辑:显示缓冲区未被填充的示例代码-发出HTTP 1.1请求(非常糟糕:)
尝试通过慢速链接发送兆字节的数据。为什么流要等到它全部存在之后再给调用者任何一个呢?如果另一方没有关闭连接怎么办?在这一点上没有“所有数据”的概念 假设您打开与另一台服务器的连接并使用大缓冲区调用
BeginRead
(或Read
),但它只发送100个字节,然后等待您的答复-您希望NetworkStream
做什么?永远不要给你数据,因为你给了它太大的缓冲区?这将产生严重的反作用
您绝对不应该假设任何流(除了MemoryStream
)将填充您提供的缓冲区。对于本地文件,FileStream
可能总是这样,但对于共享文件,我希望不是这样
编辑:显示缓冲区未被填充的示例代码-发出HTTP 1.1请求(非常糟糕:)
这当然不是NetworkStream的正常行为,获取的字节数少于请求的字节数是非常常见的。这完全取决于连接的带宽以及您响应回调的速度。您可以得到tcp/ip驱动程序堆栈中缓冲的任何内容。这肯定不是NetworkStream的正常行为,获取的字节数少于请求的字节数是非常常见的。这完全取决于连接的带宽以及您响应回调的速度。您可以得到tcp/ip驱动程序堆栈中缓冲的内容。
// 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());
}
}