![](/img/trans.png)
[英]reading stream from network using networkstream and streamreader
[英]Reading from a NetworkStream fails after StreamReader did
我有一种方法可以以非常原始的方式从Stream(实际上是NetworkStream)读取HTTP请求。 首先,我逐行阅读标题,当我看到分隔符(又名空行)时,我开始阅读正文。
代码如下:
public byte[] ReceiveHttp(Stream stream)
{
var headerLines = new List<string>();
using (var reader = new StreamReader(stream, Encoding.ASCII, false, 8192, true))
{
var requestLine = reader.ReadLine();
while (true)
{
var headerLine = reader.ReadLine();
if (string.IsNullOrEmpty(headerLine))
{
// all header lines read
break;
}
headerLine = headerLine.Trim();
headerLines.Add(headerLine);
}
}
var contentLength = RetrieveContentLengthFromHeaderLines(headerLines);
var bytes = new byte[contentLength];
var readbytesCount = 0;
while (readbytesCount < contentLength)
{
var chunkBytesCount = stream.Read(bytes, 0, contentLength);
readbytesCount += chunkBytesCount;
}
return bytes;
}
现在我的问题是,身体的后续读取有时会挂起。 我的意思是要调用stream.Read
块,直到达到某种超时。
当用某些自定义代码替换所有StreamReader.ReadLine()
(实际上是从代码中删除StreamReader
,该代码逐字节读取一行,直到发生换行符为止,该问题永远不会发生。
因此,我想StreamReader
中有某种缓冲/缓存,它可能已经读取了整个消息,但对后续的流操作隐藏了该消息。 但这只是一个猜测。
有人有一个主意吗,是什么导致了这种现象,以及如何在不使用自定义逐字节ReadLine方法的情况下解决该问题?
我已经评论过,使用StreamReader
读取http协议的标头非常复杂(无法读取)。 您必须直接阅读Stream
并“手动”拆分。
我的分线器:
// If you want to use UTF8:
// var encoding = (Encoding)Encoding.UTF8.Clone();
var encoding = Encoding.GetEncoding("iso-8859-1");
var decoder = encoding.GetDecoder();
//Encoding.ASCII
var headerLines = new List<string>();
var sb = new StringBuilder();
byte[] bytes = new byte[1];
char[] chars = new char[2];
while (true)
{
int curr = stream.ReadByte();
char ch = '\0';
bool newLine = false;
if (curr == -1)
{
newLine = true;
}
else
{
bytes[0] = (byte)curr;
// There is the possibility of a partial invalid
// character (first byte of UTF8) plus a new valid
// character. In this case decoder.GetChars will
// return 2 chars
int count = decoder.GetChars(bytes, 0, 1, chars, 0);
for (int i = 0; i < count; i++)
{
ch = chars[i];
if (ch == '\n')
{
newLine = true;
}
else
{
sb.Append(ch);
}
}
}
if (newLine)
{
string str = sb.ToString();
// Handling of \r\n
if (ch == '\n' && str[str.Length - 1] == '\r')
{
str = str.Remove(str.Length - 1);
}
str = str.Trim();
if (str.Length != 0)
{
headerLines.Add(str);
sb.Clear();
}
else
{
break;
}
}
if (curr == -1)
{
break;
}
}
请注意,对于标题,建议的编码为ISO-8859-1。 行尾可以是\\r\\n
和\\n
。 代码非常复杂,因为我想处理UTF8。 对于其他编码,它应该没有用。 请注意,在进行长度检查之前 ,我会使用Trim()
,因此仅充满空格的行仍将停止读取标头。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.