谁能指出这段代码中的缺陷吗?我正在使用 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();
}
Update
在调试器中,我可以看到整个响应立即并附加到我的 StringBuilder (响应)。当服务器完成发送响应时,连接似乎没有关闭,或者我的代码没有检测到它。
结论正如这里所说,最好利用协议提供的功能(在 HTTP 的情况下,是 Content-Length 标头)来确定事务何时完成。但是,我发现并非所有页面都设置了内容长度。所以,我现在使用混合解决方案:
对于所有交易,设置请求的Connection
标头设置为“close”,这样服务器就不会保持套接字打开。这提高了服务器在响应您的请求时关闭连接的机会。
If Content-Length
设置后,用它来确定请求何时完成。
否则,将 NetworkStream 的 RequestTimeout 属性设置为一个较大但合理的值,例如 1 秒。然后,循环播放NetworkStream.Read()
直到 a) 发生超时,或 b) 您读取的字节数少于您要求的字节数。
感谢大家出色而详细的答复。
与文档相反网络流.读取 http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.read.aspx意味着,从a获得的流TcpClient
does not当没有可用数据时,只需返回 0 作为读取的字节数 - 它会阻塞。
如果你看一下的文档TcpClient http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.aspx,你会看到这一行:
TcpClient 类提供了通过网络连接、发送和接收流数据的简单方法同步阻塞模式.
现在我的猜测是,如果你Read
调用被阻塞,这是因为服务器决定不发回任何数据。这可能是因为初始请求未正确通过。
我的第一个建议是消除StreamWriter
作为可能的原因(即缓冲/编码的细微差别),并使用NetworkStream.Write
方法。如果有效,请确保您使用了正确的参数StreamWriter
.
我的第二个建议是不要依赖于结果Read
调用以打破循环。这NetworkStream
类有一个DataAvailable
为此而设计的财产。编写接收循环的正确方法是:
NetworkStream netStream = client.GetStream();
int read = 0;
byte[] buffer = new byte[1024];
StringBuilder response = new StringBuilder();
do
{
read = netStream.Read(buffer, 0, buffer.Length);
response.Append(Encoding.ASCII.GetString(buffer, 0, read));
}
while (netStream.DataAvailable);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)