![](/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.