gpt4 book ai didi

.net - 在 C# 中使用 TcpClient 的 HTTP 客户端真的很奇怪

转载 作者:可可西里 更新时间:2023-11-01 02:31:00 26 4
gpt4 key购买 nike

我正在实现一个简单的 HTTP 客户端,它只连接到 Web 服务器并获取其默认主页。在这里,它工作得很好:

using System;
using System.Net.Sockets;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
TcpClient tc = new TcpClient();
tc.Connect("www.google.com", 80);

using (NetworkStream ns = tc.GetStream())
{
System.IO.StreamWriter sw = new System.IO.StreamWriter(ns);
System.IO.StreamReader sr = new System.IO.StreamReader(ns);

string req = "";
req += "GET / HTTP/1.0\r\n";
req += "Host: www.google.com\r\n";
req += "\r\n";

sw.Write(req);
sw.Flush();

Console.WriteLine("[reading...]");
Console.WriteLine(sr.ReadToEnd());
}
tc.Close();
Console.WriteLine("[done!]");
Console.ReadKey();
}
}
}

当我从上面的代码中删除下面的行时,程序在 sr.ReadToEnd 处阻塞。

req += "Host: www.google.com\r\n";

我什至将 sr.ReadToEnd 替换为 sr.Read,但它无法读取任何内容。我使用 Wireshark 查看发生了什么:

Screenshot of captured packets using Wireshark http://www.imagechicken.com/uploads/1252514718052893500.jpg

如您所见,在我的 GET 请求之后,Google 没有响应并且请求被一次又一次地重新传输。看来我们必须在 HTTP 请求中指定 Host 部分。奇怪的是我们不这样做。我使用 telnet 发送此请求并得到了 Google 的响应。我还捕获了telnet发送的请求,它和我的请求一模一样。

我尝试了很多其他网站(例如 Yahoo、Microsoft),但结果是一样的。

那么,telnet 中的延迟是否会导致网络服务器的行为不同(因为在 telnet 中我们实际上键入 字符而不是将它们一起发送到一个数据包中)。


另一个奇怪的问题是当我将HTTP/1.0 更改为HTTP/1.1 时,程序总是阻塞在sr.ReadToEnd 行。我想那是因为网络服务器没有关闭连接。

一种解决方案是使用Read(或ReadLine)和ns.DataAvailable 来读取响应。但我不能确定我已经阅读了所有回复。如何读取响应并确保 HTTP/1.1 请求的响应中没有剩余字节?


注意:正如 W3 所说,

the Host request-header field MUST accompany all HTTP/1.1 requests

(我为我的 HTTP/1.1 请求做了这件事)。但是我还没有看到 HTTP/1.0 这样的东西。使用 telnet 发送不带 Host header 的请求也没有任何问题。


更新:

Push 标志在 TCP 段中已设置为 1。我还尝试过 netsh winsock reset 来重置我的 TCP/IP 堆栈。测试计算机上没有防火墙或防病毒软件。数据包确实被发送了,因为安装在另一台计算机上的 Wireshark 可以捕获它。

我也尝试过其他一些请求。例如,

string req = "";
req += "GET / HTTP/1.0\r\n";
req += "s df slkjfd sdf/ s/fd \\sdf/\\\\dsfdsf \r\n";
req += "qwretyuiopasdfghjkl\r\n";
req += "Host: www.google.com\r\n";
req += "\r\n";

在所有类型的请求中,如果我省略 Host: 部分,网络服务器不会响应,如果带有 Host: 部分,即使是无效的请求(就像上面的请求一样)将得到响应(通过 400:HTTP Bad Request)。

nosHost: 部分在他的机器上不是必需的,这使情况变得更加奇怪。

最佳答案

这与使用 TcpClient 有关。

我知道这篇文章很旧。我提供此信息以防万一其他人遇到此问题。将此答案视为对上述所有答案的补充。

某些服务器需要 HTTP 主机 header ,因为它们被设置为每个 IP 地址托管多个域。作为一般规则,始终发送主机 header 。好的服务器会回复“未找到”。有些服务器根本不会回复。

当从流中读取数据的调用阻塞时,通常是因为服务器正在等待发送更多数据。当没有严格遵守 HTTP 1.1 规范时,通常会出现这种情况。为了演示这一点,请尝试省略最终的 CR LF 序列,然后从流中读取数据 - 读取调用将一直等到客户端超时或服务器通过终止连接放弃等待。

我希望这能带来一些启发......

关于.net - 在 C# 中使用 TcpClient 的 HTTP 客户端真的很奇怪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1400652/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com