訪問(wèn)一個(gè)網(wǎng)站,從本地訪問(wèn)很快,但是從客戶端訪問(wèn)大概要等待3秒的樣子。在服務(wù)器放上靜態(tài)網(wǎng)頁(yè),在客戶端訪問(wèn)則返回時(shí)間很快。
網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)公司!專注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、成都小程序開發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了豐都免費(fèi)建站歡迎大家使用!
在客戶端訪問(wèn)問(wèn)題網(wǎng)站,在客戶端用wireshark抓包
讓開發(fā)人員調(diào)查服務(wù)器端的應(yīng)用,開發(fā)人員說(shuō)之前有個(gè)小功能可以抓取客戶端MAC地址,但是看到抓的包,應(yīng)該不是用的客戶端的代碼,因?yàn)榈谝粋€(gè)web頁(yè)響應(yīng)就3秒多,要是客戶端代碼那也是后續(xù)的JS或者資源加載較慢。
開發(fā)人員給了我服務(wù)器端的代碼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);
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;
}
* 按照代碼邏輯的話,服務(wù)器應(yīng)該是用了一次SendARP 調(diào)用,但是為什么會(huì)有三個(gè)ARP請(qǐng)求產(chǎn)生,而且不同的ARP請(qǐng)求包之間的等待時(shí)間不一。所以為了驗(yàn)證這個(gè)SendARP的調(diào)用的實(shí)際操作,我用powershell 寫了上面一個(gè)sendARP 調(diào)用,然后用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 來(lái)解析一個(gè)跨網(wǎng)段的目標(biāo)IP地址,然后緊接著ping目標(biāo)主機(jī),這樣可以根據(jù)ping包的開始時(shí)間得出sendARP 的結(jié)束時(shí)間。
powershell 命令如下:
send-arp serverIP ;ping serverIP
在服務(wù)器上本機(jī)訪問(wèn)非常快,是因?yàn)榉?wù)器使用ARP請(qǐng)求查本機(jī),應(yīng)該會(huì)很快有回應(yīng)。如果其他客戶端和服務(wù)器在同一個(gè)網(wǎng)段,估計(jì)也不會(huì)慢。
客戶端慢是因?yàn)榉?wù)器在返回給客戶端http信息時(shí),先用ARP請(qǐng)求跨網(wǎng)段的客戶端IP,但是不會(huì)有ARP回應(yīng),因?yàn)槁酚傻脑?,客戶端看不到服?wù)器的ARP請(qǐng)求,而SendARP函數(shù)的超時(shí)時(shí)間大概為3.1秒,所以跨網(wǎng)段的客戶端收到服務(wù)器的一個(gè)HTTP響應(yīng)在3.28秒左右。同樣單純?cè)诳蛻舳俗グ荒芊治龀龇?wù)器應(yīng)用有問(wèn)題,但是說(shuō)不出具體的問(wèn)題。
靜態(tài)網(wǎng)頁(yè)快是因?yàn)椋o態(tài)網(wǎng)頁(yè)不執(zhí)行服務(wù)器端代碼,所以不會(huì)執(zhí)行ARP查詢。