System.IO.Stream.Read gets stuck



我使用System.IO.Stream.Read与服务器端建立了HTTP连接,以读取HTTP请求正文消息。问题是,几分钟后,服务器会卡在Read语句上,直到套接字超时或客户端关闭连接才继续。

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循环。

为什么卡住了,不能继续读取数据?

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

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循环将成为"读取0,添加0,读取0,添加0,添加0,读取0,读取0,读取0,添加0,读取0,添加0"的紧密循环。

作为最后一点,您的方法建议您根据传入的内容长度头分配byte[];只是一个警告:请确保您对此进行了安全检查,并将其限制为合理的值,否则DOS攻击是微不足道的。此外,如果可能的话我建议尽量使用流API,以避免必须一次将其全部加载到内存中(除非您限制了传入的大小,因此这不是一个问题)。

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

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);
}

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

byte[] buffer = stream.Stream.ToArray()

或者复制到另一个缓冲区:

byte[] data = stream.Stream.ToArray();
Array.CopyTo(data , buffer.Buffer, data.Length)

我有过类似的错误,只有客户端没有刷新他们的流。System.IO.Stream.Read上的MSDN文档说:"在没有可用数据的情况下,实现将阻塞直到至少一个字节的数据可以被读取。"由于某些原因,没有可用的数据。我认为你可以设置一个特定的ReadTimeout,并在相当短的时间后停止等待更多的数据。

一个相关的问题也被贴在这里:c# NetworkStream。读古怪。也许他的解决方案也能帮到你。

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

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

当将代码更改为仅与套接字一起工作并直接从套接字执行读取时,它已经修复了这个问题。

相关内容

  • 没有找到相关文章

最新更新