訪問一個網站,從本地訪問很快,可是從客戶端訪問大概要等待3秒的樣子。在服務器放上靜態網頁,在客戶端訪問則返回時間很快。web
在客戶端訪問問題網站,在客戶端用wireshark抓包shell
讓開發人員調查服務器端的應用,開發人員說以前有個小功能能夠抓取客戶端MAC地址,可是看到抓的包,應該不是用的客戶端的代碼,由於第一個web頁響應就3秒多,要是客戶端代碼那也是後續的JS或者資源加載較慢。c#
開發人員給了我服務器端的代碼C#
``` c#
[DllImport("Iphlpapi.dll")]
private static extern int SendARP(Int32 dest, Int32 host, ref Int64 mac, ref Int32 length);
[DllImport("Ws2_32.dll")]
private static extern Int32 inet_addr(string ip);api
public string getClientMac(string userip) { if (string.IsNullOrEmpty(userip)) return null; //string userip = Request.UserHostAddress; string strClientIP = userip.ToString().Trim(); Int32 ldest = inet_addr(strClientIP); Int32 lhost = inet_addr(""); Int64 macinfo = new Int64(); Int32 len = 6; int res = SendARP(ldest, 0, ref macinfo, ref len); string mac_src = macinfo.ToString("X"); //if (mac_src == "0") //{ // ip = userip; //} while (mac_src.Length < 12) { mac_src = mac_src.Insert(0, "0"); } string mac_dest = ""; for (int i = 0; i < 11; i++) { if (0 == (i % 2)) { if (i == 10) { mac_dest = mac_dest.Insert(0, mac_src.Substring(i, 2)); } else { mac_dest = "-" + mac_dest.Insert(0, mac_src.Substring(i, 2)); } } } return mac_dest; }
* 按照代碼邏輯的話,服務器應該是用了一次SendARP 調用,可是爲何會有三個ARP請求產生,並且不一樣的ARP請求包之間的等待時間不一。因此爲了驗證這個SendARP的調用的實際操做,我用powershell 寫了上面一個sendARP 調用,而後用wireshark抓包。 ``` powershell Function Send-Arp { param( [string]$DstIpAddress, [string]$SrcIpAddress = 0 ) $signature = @" [DllImport("iphlpapi.dll", ExactSpelling=true)] public static extern int SendARP( uint DestIP, uint SrcIP, byte[] pMacAddr, ref int PhyAddrLen); "@ Add-Type -MemberDefinition $signature -Name Utils -Namespace Network try { $DstIp = [System.Net.IPAddress]::Parse($DstIpAddress) $DstIp = [System.BitConverter]::ToInt32($DstIp.GetAddressBytes(), 0) } catch { Write-Error "Could not convert $($DstIpAddress) to an IpAddress type. Please verify your value is in the proper format and try again." break } if ($SrcIpAddress -ne 0) { try { $SrcIp = [System.Net.IPAddress]::Parse($SrcIpAddress) $SrcIp = [System.BitConverter]::ToInt32($SrcIp.GetAddressBytes(), 0) } catch { Write-Error "Could not convert $($SrcIpAddress) to an IpAddress type. Please verify your value is in the proper format and try again." break } } else { $SrcIp = $SrcIpAddress } $New = New-Object PSObject -Property @{ IpAddress = $DstIpAddress PhysicalAddress = '' Description = '' ArpSuccess = $true } | Select-Object IpAddress,PhysicalAddress,ArpSuccess,Description $MacAddress = New-Object Byte[] 6 $MacAddressLength = [uint32]$MacAddress.Length $Ret = [Network.Utils]::SendARP($DstIp, $SrcIp, $MacAddress, [ref]$MacAddressLength) if ($Ret -ne 0) { $New.Description = "An error was returned from SendArp() with error code: $($Ret)" $New.ArpSuccess = $false } else { $MacFinal = @() foreach ($b in $MacAddress) { $MacFinal += $b.ToString('X2') } $New.PhysicalAddress = ($MacFinal -join ':') } Write-Output $New }
使用powershell 來解析一個跨網段的目標IP地址,而後緊接着ping目標主機,這樣能夠根據ping包的開始時間得出sendARP 的結束時間。
powershell 命令以下:服務器
send-arp serverIP ;ping serverIP
在服務器上本機訪問很是快,是由於服務器使用ARP請求查本機,應該會很快有迴應。若是其餘客戶端和服務器在同一個網段,估計也不會慢。網絡
客戶端慢是由於服務器在返回給客戶端http信息時,先用ARP請求跨網段的客戶端IP,可是不會有ARP迴應,由於路由的緣由,客戶端看不到服務器的ARP請求,而SendARP函數的超時時間大概爲3.1秒,因此跨網段的客戶端收到服務器的一個HTTP響應在3.28秒左右。一樣單純在客戶端抓包只能分析出服務器應用有問題,可是說不出具體的問題。tcp
靜態網頁快是由於,靜態網頁不執行服務器端代碼,因此不會執行ARP查詢。ide