【发布时间】:2010-02-03 17:17:10
【问题描述】:
谁能指出这段代码的缺陷?我正在使用 TcpClient 检索一些 HTML。与 IIS 服务器通信时,NetworkStream.Read() 似乎永远不会完成。如果我改用 Fiddler 代理,它可以正常工作,但是当直接与目标服务器对话时,.read() 循环不会退出,直到连接异常出现“远程服务器已关闭连接”之类的错误。
internal TcpClient Client { get; set; }
/// bunch of other code here...
try
{
NetworkStream ns = Client.GetStream();
StreamWriter sw = new StreamWriter(ns);
sw.Write(request);
sw.Flush();
byte[] buffer = new byte[1024];
int read=0;
try
{
while ((read = ns.Read(buffer, 0, buffer.Length)) > 0)
{
response.AppendFormat("{0}", Encoding.ASCII.GetString(buffer, 0, read));
}
}
catch //(SocketException se)
{
}
finally
{
Close();
}
更新
在调试器中,我可以看到整个响应立即通过并附加到我的 StringBuilder(响应)中。当服务器完成发送响应时,似乎连接没有关闭,或者我的代码没有检测到它。
结论 正如这里所说,最好利用协议的提供(在 HTTP 的情况下,Content-Length 标头)来确定事务何时完成。但是,我发现并非所有页面都设置了内容长度。所以,我现在使用的是混合解决方案:
对于所有事务,将请求的
Connection标头设置为“关闭”,以阻止服务器保持套接字打开。这提高了服务器在响应您的请求时关闭连接的机会。如果设置了
Content-Length,则使用它来确定请求何时完成。否则,将 NetworkStream 的 RequestTimeout 属性设置为一个较大但合理的值,例如 1 秒。然后,在
NetworkStream.Read()上循环,直到 a) 发生超时,或者 b) 您读取的字节数少于请求的字节数。
感谢大家出色而详细的回复。
【问题讨论】:
-
我认为你应该分块写请求。这将帮助您调试。
-
写入工作正常;这是导致问题的读取。
-
它是否阻塞了
Read调用,或者您是否正在无限执行循环?如果是后者,从流中出来的是什么?你查过response的内容了吗? -
是否有任何内容写入 IIS 日志?
-
@Aaronaugh 它正在阻止读取。
标签: c# asp.net tcpclient networkstream