首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >System.IO.Stream.Read卡住了

System.IO.Stream.Read卡住了
EN

Stack Overflow用户
提问于 2011-09-15 08:02:46
回答 4查看 4.3K关注 0票数 1

我与服务器端有HTTP连接,使用System.IO.Stream.Read读取HTTP消息。问题是,一旦在几分钟内,服务器就会卡在Read语句上,并且在到达套接字超时或客户端关闭连接之前不会继续。

代码语言:javascript
运行
复制
int bytesRead = 0;

while (bytesRead < contentLength)
{
  int got = stream.Stream.Read(buffer.Buffer, bytesRead, contentLength - bytesRead);
  bytesRead += got;
}
  1. 如果流没有contentLength变量指定的数据量,则可能发生这种情况。情况并非如此,因为当使用WireShark跟踪tcp流时,我看到整个消息体(如contentLength所指定的)已到达服务器机器。
  2. 只有在第一次“使用”while循环时才发生这种情况,也就是说,只有在第一次流没有"contentLength“字节数的情况下,才会在一次尝试中读取字节数,并且不得不重新输入while循环。

为什么它会被卡住而不继续读取数据?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-09-19 06:27:33

这似乎与以下事实有关:我使用的是NetworkStream的Read方法(这是上面代码中看到的调用)和通过将NetworkStream对象传递给它的构造函数创建的StreamReader

NetworkStream.Read用于读取http请求消息体,而StreamReader.Read用于读取请求的其余部分(起始行、标头.)。虽然调用是由同一个线程同步进行的,但这可能是我所经历的行为的原因。

当将代码更改为只使用套接字并直接从套接字执行读取时,它解决了这个问题。

票数 0
EN

Stack Overflow用户

发布于 2011-09-15 08:10:03

我想知道流是否报告提前终止;您还应该查看Read是否返回了一个非正数,即

代码语言:javascript
运行
复制
while (bytesRead < contentLength)
{
  int got = stream.Stream.Read(
       buffer.Buffer, bytesRead, contentLength - bytesRead);
  if(got <= 0) throw new EndOfStreamException(string.Format(
       "Expected {0} bytes; {1} bytes received", contentLength, bytesRead));
  bytesRead += got;
}

基本上,如果流已经关闭,Read的每个调用都将返回非正(可能为0),因此您的while循环将成为"read 0,add 0,read 0,add 0“的紧密循环。

作为最后一点,您的方法建议您根据传入的内容长度标头分配一个byte[];只是一个警告:确保您的理智-检查它并将其限制在正常值,否则一个DOS攻击是微不足道的。此外,如果可能的话,我建议在可能的情况下尝试使用流API,以避免将其同时加载到内存中(除非您限制了传入的大小,这样就不需要担心了)。

票数 1
EN

Stack Overflow用户

发布于 2011-09-15 08:12:42

尝试这个实现,您的计数(contentLength - bytesRead)是错误的。应该是缓冲区大小。

代码语言:javascript
运行
复制
byte[] buffer = new byte[bufferSize];
int count;
while ((count = stream.Stream.Read(buffer, 0, buffer.Length)) != 0)
{ 
    // do something with the buffer using count as the end marker
    destination.Write(buffer, 0, count);
}

如果您只想从流中得到一个字节数组,这更像是您正在尝试的:

代码语言:javascript
运行
复制
byte[] buffer = stream.Stream.ToArray()

或复制到另一个缓冲区:

代码语言:javascript
运行
复制
byte[] data = stream.Stream.ToArray();
Array.CopyTo(data , buffer.Buffer, data.Length)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7427611

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档