死灵术。
对于那些仍在使用 .NET 2.0的人
来说,如果您知道如何操作,这实际上很容易。
问题是,您不能设置主机标头,因为框架不允许您在运行时更改值。(.net framework 4.0+ 将允许您在 httpwebrequest 中覆盖主机)。
下一次尝试将设置带有反射的标头 - 如此处最受好评的答案所示 - 绕过它,这将让您更改标头值。但是在运行时,它会用url的 host 部分覆盖这个值,这意味着反射不会给你带来任何东西,这就是为什么我不明白为什么人们继续投票的原因。
如果 dns-name 不存在,坦率地说,这是您首先要执行此操作的唯一情况,您无法设置它,因为 .NET 无法解析它,而且您也无法覆盖 .NET DNS 解析器。
但是您可以做的是设置一个与目标服务器具有完全相同 IP 的网络代理。
所以,如果你的服务器 IP 是 28.14.88.71:
public class myweb : System.Net.WebClient
{
protected override System.Net.WebRequest GetWebRequest(System.Uri address)
{
System.Net.WebRequest request = (System.Net.WebRequest)base.GetWebRequest(address);
//string host = "redmine.nonexistantdomain.com";
//request.Headers.GetType().InvokeMember("ChangeInternal",
// System.Reflection.BindingFlags.NonPublic |
// System.Reflection.BindingFlags.Instance |
// System.Reflection.BindingFlags.InvokeMethod, null,
// request.Headers, new object[] { "Host", host }
//);
//server IP and port
request.Proxy = new System.Net.WebProxy("http://28.14.88.71:80");
// .NET 4.0 only
System.Net.HttpWebRequest foo = (System.Net.HttpWebRequest)request;
//foo.Host = host;
// The below reflection-based operation is not necessary,
// if the server speaks HTTP 1.1 correctly
// and the firewall doesn't interfere
// https://yoursunny.com/t/2009/HttpWebRequest-IP/
System.Reflection.FieldInfo horribleProxyServicePoint = (typeof(System.Net.ServicePoint))
.GetField("m_ProxyServicePoint", System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance);
horribleProxyServicePoint.SetValue(foo.ServicePoint, false);
return foo; // or return request; if you don't neet this
}
}
瞧,现在
myweb wc = new myweb();
string str = wc.DownloadString("http://redmine.netexistantdomain.com");
如果 28.14.88.71 是一个具有基于虚拟名称的托管(基于 http-host-header)的网络服务器,那么您会得到正确的页面。
现在您对 WebRequest 和 WebClient 的原始问题有了正确的答案。我认为使用自定义套接字来执行此操作是错误的方法,尤其是在应该使用 SSL 并且实际解决方案如此简单时......