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               //後面的暫時不用看,已經獲取到客戶端訪問IP12                 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 AssignNullToNotNullAttribute15                 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             catch18             {19                 // ignored20             }21             return tempIp;22         }

複製代碼

 

 但是問題出現了,爲什麼我瀏覽器獲取的數據可以得到本機的IP,但是我建立的連接獲取的請求卻是這樣

經過分析後發現,這個網址試用iframe框架進行處理,無法獲取到frame框架的內部信息,然後抓去frame信息發現其實他真正請求的路徑爲 http://1212.ip138.com/ic.asp,該網站的編碼格式爲gb2312,再次發送請求獲取返回數據:

雖然大概瞭解的一些,但是比如用戶用代理服務器訪問等一系列的問題還是需要我繼續去探索!

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章