如何确定 NetworkStream 中何时不再有数据可供读取?
我有一个 Web 应用程序,它使用 TCP 连接连接到服务器并读取二进制文档,然后将其写入其响应对象。 换句话说,它使用自定义协议从后端服务器传输文件,并通过 HTTP 将文件返回给客户端。
服务器发送状态代码和 mime 类型,我成功读取,然后写入文件内容并关闭套接字。 这似乎工作正常。
客户端(C# Web 应用程序)读取数据:
private NetworkStream stream_;
public void WriteDocument(HttpResponse response)
{
while (stream_.DataAvailable)
{
const int bufsize = 4 * 1024;
byte[] buffer = new byte[bufsize];
int nbytes = stream_.Read(buffer, 0, bufsize);
if (nbytes > 0)
{
if (nbytes < bufsize)
Array.Resize<byte>(ref buffer, nbytes);
response.BinaryWrite(buffer);
}
}
response.End();
}
这似乎总是在所有数据到达之前退出读取循环。 我究竟做错了什么?
I have a web app which connects to a server using a TCP connection and reads a binary document which it then writes to its response object. In other words it's transferring a file from a backend server using a custom protocol and returning that file to its client through HTTP.
The server sends a status code and a mime type, which I read successfully and then writes the contents of the file and closes the socket. This seems to work fine.
The client (a C# web app), reads the data:
private NetworkStream stream_;
public void WriteDocument(HttpResponse response)
{
while (stream_.DataAvailable)
{
const int bufsize = 4 * 1024;
byte[] buffer = new byte[bufsize];
int nbytes = stream_.Read(buffer, 0, bufsize);
if (nbytes > 0)
{
if (nbytes < bufsize)
Array.Resize<byte>(ref buffer, nbytes);
response.BinaryWrite(buffer);
}
}
response.End();
}
This seems to always exit the read loop before all the data has arrived. What am I doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
问题的根源是这一行:
DataAvailable 只是意味着流缓冲区中有数据可供读取和处理。 它不保证已到达流的“末尾”。 特别是,如果传输有任何暂停,或者如果您的发送方比您的阅读器慢,则 DataAvailable 可能为 false。
The root of your problem is this line:
DataAvailable simply means there's data in the stream buffer ready to be read and processed. It makes no guarantee about the 'end' of the stream having been reached. In particular, DataAvailable can be false if there's any pause in transmission, or if your sender is slower than your reader.
不确定 .Net 中的工作原理,但在我工作过的大多数环境中,当连接关闭时,Read() 返回 0 字节。 所以你会做类似的事情:
Not sure how things work in .Net, but in most environments I've worked in Read() returns 0 bytes when the connection is closed. So you'd do something like:
我将直接将
OutputStream
与通用函数一起使用。 通过Stream
,您可以控制Flush
。I would use the
OutputStream
directly with a general-purpose function. With theStream
, you can controlFlush
.这就是我所做的。 通常需要内容长度来知道何时结束数据存储循环。 如果您的协议没有发送预期作为标头的数据量,那么它应该发送一些标记来表示传输结束。
DataAvailable 属性只是发出信号,表示现在是否有数据要从套接字读取,它不(也不能)知道是否还有更多数据要发送。 要检查套接字是否仍然打开,您可以测试stream_.Socket.Connected && Stream_.Socket.Readable
Here's what I do. Usually the content length is desired to know when to end the data storing loop. If your protocol does not send the amount of data to expect as a header then it should send some marker to signal the end of transmission.
The DataAvailable property just signals if there's data to read from the socket NOW, it doesn't (and cannot) know if there's more data to be sent or not. To check that the socket is still open you can test for stream_.Socket.Connected && stream_.Socket.Readable