C#服务器获取客户端IP地址以及归属地探秘
背景:博主本是一位Windows桌面应用程序开发工程师,对网络通信一知半解。一日老婆逛完某宝,问:“为什么他们知道我的地址呢,他们是怎么获取我的地址的呢?”
顺着这个问题我们的探秘开始:
第一步:简单的服务搭建
思路,通过HttpListener在本地搭建一个简易的服务器,开发程序为控制台接口,核心类 HttpListenerService:
方法 Start()开启线程池针对指定IP进行监听,本地的端口选取的9527(周星驰唐伯虎点秋香在华府的编号)
public void Start(object obj)
{
try
{
//指定身份验证 Anonymous匿名访问
_httpListener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
//GetLocalIpAddress()----获取本地IP的方法
_httpListener.Prefixes.Add("http://" + GetLocalIpAddress() + ":9527/");
_httpListener.Start();
//等待请求连接
while (true)
{
//等待请求连接
//没有请求则GetContext处于阻塞状态
var ctx = _httpListener.GetContext();
ThreadPool.QueueUserWorkItem(TaskProc, ctx);
}
}
catch (Exception ex)
{
throw;
}
}
第二步:获取客户端request的IP地址
网上查询了很多例子,感觉太复杂了,自己通过VS的快速监视功能发现有一个属性 RemoteEndPoint 可以获取客户端IP和端口号 ,其实应该根据Get和POST进行区分,为了方便暂时省略
1 private void TaskProc(object o)
2 {
3 try
4 {;
5 var ctx = (HttpListenerContext) o;
6 string ipAddress = null;
7 if (ctx.Request.RemoteEndPoint != null)
8 {
9 ipAddress = ctx.Request.RemoteEndPoint.Address.ToString();
10 }
11 //后面的暂时不用看,已经获取到客户端访问IP
12 var encoding = Encoding.GetEncoding("gb2312");
13 var callbackData = JsonConvert.SerializeObject(IpGetCity(GetOuterNetIp()));
14 var data = encoding.GetBytes(callbackData);
15 ctx.Response.StatusCode = 200;
16 ctx.Response.Close(data, false);
17 }
18 catch (Exception ex)
19 {
20 }
21 }
第三步:如何根据客户端的IP获取,客户端所在的地址,因为事情起源来自淘宝,所以就 查询淘宝是否有类似的接口,果然经过搜索后查到 http://ip.taobao.com/service/getIpInfo.php?ip= 客户IP的Json对象,通过Fiddler解析返回数据,创建对应Json格式对象,封装获取方法

1 public static Result IpGetCity(string ipAddres)
2 {
3 try
4 {
5 if (!ValidateIpAddress(ipAddres)) return null;
6
7 var url = new Uri("http://ip.taobao.com/service/getIpInfo.php?ip=" + ipAddres);
8 var request = (HttpWebRequest) WebRequest.Create(url);
9 request.Timeout = 1000*5;
10 request.KeepAlive = false;
11 request.Method = "GET";
12 var resoponse = request.GetResponse();
13 string pageHtml;
14 // ReSharper disable once AssignNullToNotNullAttribute
15 using (var stream = new StreamReader(resoponse.GetResponseStream()))
16 {
17 pageHtml = stream.ReadToEnd();
18 }
19 var data = JsonConvert.DeserializeObject<Result>(pageHtml);
20 return data;
21 }
22 catch (WebException webEx)
23 {
24 throw;
25 }
26 }
第四步:测试。 因为本地是局域网,发送IP地址后返回肯定为空,先尝试查询本地外网IP,那么如何获取本地的外网IP呢?还是同前面的思路一样,网络查询类似的接口,百度一下直接根据第一个搜索的结果查询,http://1212.ip138.com,建立webrequest请求,抓取Html数据
1 public static string GetOuterNetIp()
2 {
3 var tempIp = "";
4 try
5 {
6 WebRequest wr = (HttpWebRequest) WebRequest.Create("http://1212.ip138.com");
7 var stream = wr.GetResponse().GetResponseStream();
8 var sr = new StreamReader(stream, Encoding.GetEncoding("gb2312"));
9 var all = sr.ReadToEnd();
10 //读取网站的数据
11 var start = all.IndexOf("您的IP是:[", StringComparison.Ordinal) + 7;
12 var end = all.IndexOf("]", start, StringComparison.Ordinal);
13 tempIp = all.Substring(start, end - start);
14 sr.Close();
15 stream.Close();
16 }
17 catch
18 {
19 // ignored
20 }
21 return tempIp;
22 }
但是问题出现了,为什么我浏览器获取的数据可以得到本机的IP,但是我建立的连接获取的请求却是这样


经过分析后发现,这个网址试用iframe框架进行处理,无法获取到frame框架的内部信息,然后抓去frame信息发现其实他真正请求的路径为 http://1212.ip138.com/ic.asp,该网站的编码格式为gb2312,再次发送请求获取返回数据:

虽然大概了解的一些,但是比如用户用代理服务器访问等一系列的问题还是需要我继续去探索!

浙公网安备 33010602011771号