博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WebRequest对DNS说:没有你我依然可以
阅读量:6140 次
发布时间:2019-06-21

本文共 2613 字,大约阅读时间需要 8 分钟。

前言

标题中的“没有你我依然可以”引用自王杰一首歌的名字《没有你我依然可以》。

WebRequest - 就是大家熟知的System.Net.WebRequest,.NET世界中代码们用的“浏览器”。

DNS - Domain Name System,就是大家熟知的将域名解析为IP地址的系统。

起因

今天园友sixserve在博问上问了一个问题 - :

RT,一个IP上的IIS可能绑定了多个站点,直接请求的话IIS不知道你要请求哪个站点,所以有什么办法可以把域名信息跟上好让IIS知道,不要用WebClient和其他的,这个域名绑定的是内网地址,如果用WebClient、WebRequest这样的话要改host文件了。

问题解读:

1. 如何通过客户端(不是浏览器,是一段C#代码)访问目标Web服务器上绑定的指定域名的站点(比如假设这里是q.cnblogs.com),而这个域名在DNS与客户端的hosts文件中没有对应的IP地址解析,所以只能通过IP地址进行访问(比如这里假设是61.155.169.118)。但是,由于这个Web服务器绑定了多个站点,需要通过不同的主机名(域名)进行区分,仅有IP地址,Web服务器无法知道你要访问的目标主机名。也就是你通过 http://61.155.169.118 无法访问到 http://q.cnblogs.com(由于没有主机名信息);通过 http://q.cnblogs.com 访问,请求根本无法到达目标Web服务器(由于没有DNS解析,客户端不知道目标IP地址)。

2. 问题也就变成了:通过IP地址访问目标Web服务器时,如何将主机名的信息传递给Web服务器?园友sixserve想通过Socket来实现,并强调了不要用WebClient,WebRequest这类的(可能是基于这样的假设:用它们只能在域名与IP地址之间选一个。之前我也是这么认为的)。

问题解决过程

早上看到这个提问时,我立即来了兴趣。因为昨天刚刚学习了阮一峰的,正在劲头上。

另外,提问者强调了不要用WebRequest,我偏偏要用WebRequest。有首歌叫《偏偏喜欢你》,即使对方说“我一点也不喜欢你”,你也可以继续偏偏喜欢你,执着可以创造奇迹。

这里对WebRequest的执着,并不是偏执,是经过考虑的。只要解决了DNS解析问题,就能用WebRequest通过主机名访问。那如何解决DNS解析的问题呢?不能给DNS添加记录,不能修改hosts文件,那怎么办?

1. 首先,我想到的解决思路是:能不能找到一种方法向通过C#代码向本地DNS缓存中添加一条解析记录。因为在DNS解析过程中,会先在本地DNS缓存中查找。。。但此路不通,未找到实现方法。

2. 后来,在stackoverflow上找到一种:hook WSOCK32.DLL中对应的API,也就是在客户端进行DNS解析的过程中,会调用WSOCK32.DLL中的API,只要截获这个调用请求,对于要解析的主机名返回对应的IP即可。回答者给出了C++实现代码:

struct hostent FAR * WSAAPI MyGetHostByName(IN const char FAR * name){    // Call the regular function     struct hostent* ret = GetHostByNameFunction(name);    // Check if it's the hostname you want to reroute    if ( strcmp(host, (char*)name) == 0 )    {        // Edit the IP returned by the regular gethostbyname        ret->h_addr_list[0] = hostIP;        ret->h_length = 15;    }    // Return the result    return ret;}

并提供了C#的实现思路,通过  进行hook。

这个方法虽然可行,但太复杂,并没有成为心目中的“她” —— 还是简单点好。

这个复杂的解决方法反而影响了我继续解决问题的兴趣,几乎准备放弃对这个问题的继续研究。

问题解决方法

还好,我没有轻易放弃,继续思考可能的解决方法,并组合各种关键词进行搜索。。。

很多时候,柳暗花明就在你最因难、最无助、最精疲力尽、最想放弃的前方100米。。。

通过关键词“c# add to hosts”,再次来到stackoverflow,在一个提问  的最佳答案的下方有一个,没有任何“推荐”:

当时就眼前一亮,心中隐约感觉到就是“她”。。。接下来只需验证一下刚刚发现的这个“她”是不是就是一直在寻找的“她”。。。

功夫不负有心人,事实证明就是“她”,终于找到了!下面的代码就是见证:

[Fact]//http://q.cnblogs.com/q/38881/public void Q38881_Test(){    var request = WebRequest.Create("http://61.155.169.118") as HttpWebRequest;    request.Host = "q.cnblogs.com";    using (var response = request.GetResponse())    {        using (var sr = new StreamReader(response.GetResponseStream()))        {            Console.WriteLine(sr.ReadToEnd());        }    }}

代码运行结果:

小结

写了这么多,就是为了这一行代码:request.Host = "q.cnblogs.com"; 等了那么多年,就是为了那一个人。代码如此,生活也是如此。。。结果往往很简单,而真正激动人心的是其中的过程。

这行代码的意义在于可以让WebRequest不依赖DNS,于是才有了这样的故事 —— WebRequest对DNS说:没有你我依然可以。

转载地址:http://tucya.baihongyu.com/

你可能感兴趣的文章
HDOJ 2020 绝对值排序
查看>>
HDOJ/HDU 2560 Buildings(嗯~水题)
查看>>
Maven编译时跳过Test
查看>>
Spring Boot 整合Spring Security 和Swagger2 遇到的问题小结
查看>>
[20170628]12C ORA-54032.txt
查看>>
除以2
查看>>
高可用集群原理解析
查看>>
Nginx配置URL转向tomcat
查看>>
极客Web前端开发资源大荟萃#001
查看>>
让div固定在某个位置
查看>>
Java开发环境Docker镜像
查看>>
从无到有,WebService Apache Axis2初步实践
查看>>
任务调度(一)——jdk自带的Timer
查看>>
UIKit框架(15)PCH头文件
查看>>
整理看到的好的文档
查看>>
Linux磁盘管理和文件系统管理
查看>>
linux运维人员的成功面试总结案例分享
查看>>
Windows DHCP Server基于MAC地址过滤客户端请求实现IP地址的分配
查看>>
命令查询每个文件文件数
查看>>
《跟阿铭学Linux》第8章 文档的压缩与打包:课后习题与答案
查看>>