【发布时间】:2017-07-16 12:00:15
【问题描述】:
我正在用 C# 编写一个 TCP 客户端和一个服务器,它们使用手动编写的 HTTP 请求来相互通信。我遇到的麻烦是使用StreamReader 阅读Network Stream。到目前为止,我尝试了很多方法,但无济于事。
我从 TCP 客户端收到的请求有多种形式。对于更新数据库,请求如下所示(CRLF 是我用来表示"\r\n" 字符串的常量):
HTTP 1.0:
“POST /”+名称+“HTTP/1.0”+CRLF+“内容长度:”+长度+ CRLF + CRLF + 位置;
HTTP 1.1:
“POST/HTTP/1.1”+CRLF+主机名+“内容长度:”+长度+ CRLF + CRLF + nameLocString;
请求的格式正确,并且客户端正确发送它们 - 我已经在我有权访问的服务器上对此进行了测试,该服务器可以毫无问题地响应它们。
我遇到的问题与我的 TCP 侦听器代码有关。为了避免发布整个代码,我将仅包含有问题的代码部分(通过调试发现)。
服务器代码:
NetworkStream socketStream = new NetworkStream(connection);
StreamReader sr = new StreamReader(socketStream);
string input = ReadAllLinesWithNull(sr); // reading version 1
string input = ReadAllLinesWithEndOfStream(sr); // reading version 2
string input = ReadAllLinesWithPeek(sr); // reading version 3
string input = sr.ReadToEnd(); // reading version 4
而使用的方法有:
static string ReadAllLinesWithNull(StreamReader sr)
{
string input;
string nextLine;
input = sr.ReadLine();
while ((nextLine = sr.ReadLine()) != null)
{
Console.WriteLine(input);
input += nextLine;
}
sr.Close();
return input;
}
static string ReadAllLinesWithEndOfStream(StreamReader sr)
{
string input = "";
while (!sr.EndOfStream)
{
input += sr.ReadLine();
}
sr.Close();
return input;
}
static string ReadAllLinesWithPeek(StreamReader sr)
{
string input = "";
while (sr.Peek() >= 0)
{
input += sr.ReadLine();
}
sr.Close();
return input;
}
这些阅读方法都不起作用。设置了连接超时后,我收到了 IO 异常,即读取时间过长/连接被强制关闭。我关闭了超时,读取花费了无限的时间。
感谢使用ReadLine()s,我能够为所有版本的协议挑选出最终挂起的位置,并且发现当有两个 CRLF 的集群 ("\r\n\r\n") 时,Stream Reader无法应对并陷入困境。
您对如何解决这个问题有什么建议吗?我需要按照规范使用具有多个 CRLF 的版本。
如果您需要任何其他信息,我会尽量以 sson 的形式提供。
【问题讨论】:
-
您能否发布“无法应对并卡住”的代码,因为您发布的内容对我来说很好。请注意
ReadLinedoes not include any terminating returns or linefeeds,因此您发布的内容将返回所有连接的内容,并删除了回车和换行符。 -
@DourHighArch 我提供的代码对我来说都是失败的。我检查并且客户端正确地将提到的 HTTP 请求写入流并刷新它们,然后当我使用任何 ReadLine 方法读取时,我从来没有得到任何超过 Content-Length: + length + CRLF + CRLF 的内容。当我设置超时时,它要么无限期地读取,要么抛出异常。感谢您提供有关 ReadLine 的说明。我首先想让它读起来尽可能简单,然后再看看正确的读法。我用新的简单服务器测试了读取(只是读取和回显),它有同样的问题。
标签: c# network-programming streamreader tcplistener networkstream