问题

访问一个网站,从本地访问很快,但是从客户端访问大概要等待3秒的样子。在服务器放上静态网页,在客户端访问则返回时间很快。

排错步骤

  • 在客户端访问问题网站,在客户端用wireshark抓包

    1. 用tcp 三次握手及客户端请求与服务器返回的ACK来判断是否存在线路或者服务器忙问题,发现不是。348-349 显示出服务器响应很快。 349-498 之间用了3.28秒,说明这是服务器应用的问题。

  • 让开发人员调查服务器端的应用,开发人员说之前有个小功能可以抓取客户端MAC地址,但是看到抓的包,应该不是用的客户端的代码,因为第一个web页响应就3秒多,要是客户端代码那也是后续的JS或者资源加载较慢。

  • 不管三七二十一,在服务器端也抓了下包。过滤下arp 和http的包看看,过滤后发现有三个ARP请求,但是没有对应回应。另外仔细看ARP请求的具体内容也不对,服务器用ARP请求去解析客户端的MAC地址应该是不对的,原因是服务器和客户端不在一个网段,正常的跨网段的ARP请求是同一个网段才会用的,如果跨网段那应该去解析路由器的MAC地址。所以这些ARP请求有问题。

  • 开发人员注释掉了客户端ARP地址查询的代码。访问速度瞬间提升了。
  • 开发人员同时注意到客户端ARP地址查询的结果为00-00-00-00-00-00,和我们的服务器上的抓包结果一致,因为去请求一个跨网段IP地址的MAC,所以目标地址不会收到,因为ARP广播会在路由器端终止。

揭开真相

  • 开发人员给了我服务器端的代码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;
    }

* 按照代码逻辑的话,服务器应该是用了一次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以及ICMP来验证,SendARP函数会发送三个ARP包,可能也会等待超时,因为没有ARP包回应,这个测试的时间大概也在3.1秒左右,符合问题现象。

最后总结:

  1. 在服务器上本机访问非常快,是因为服务器使用ARP请求查本机,应该会很快有回应。如果其他客户端和服务器在同一个网段,估计也不会慢。

  2. 客户端慢是因为服务器在返回给客户端http信息时,先用ARP请求跨网段的客户端IP,但是不会有ARP回应,因为路由的原因,客户端看不到服务器的ARP请求,而SendARP函数的超时时间大概为3.1秒,所以跨网段的客户端收到服务器的一个HTTP响应在3.28秒左右。同样单纯在客户端抓包只能分析出服务器应用有问题,但是说不出具体的问题。

  3. 静态网页快是因为,静态网页不执行服务器端代码,所以不会执行ARP查询。

  4. 另外开发人员也应该熟悉常见的网络协议,像这次的代码就会仅仅在特定场景下工作,如果网站是面向互联网的话,那这个代码将不会起到作用,反而影响性能

转载于:https://blog.51cto.com/yoke88/2053667

无法回应的ARP请求包导致的网站缓慢问题排错相关推荐

  1. ARP实验(ARP请求、回应包结构与ARP代理配置)

    ARP实验 要求 过程 要求 1.在本地电脑搭建环境进行ARP实验,要求能实现查看ARP请求与回应.ARP代理; 2.分析ARP请求与回应的报文结构,分析免费ARP的报文结构特征; 3.实现ARP代理 ...

  2. 计算机网络课程设计——发送和接收TCP数据包以及发送和捕获ARP数据包

    1.课程设计要求: 发送和接收TCP数据包:TCP是一种面向连接的.可靠的传输层协议.TCP协议工作在网络层IP协议的基础上.本课程设计的目的是设计一个发送和接收TCP数据包的程序,其功能是填充一个T ...

  3. python arp_用Python构造ARP请求、扫描、欺骗

    0. ARP介绍 首先,先回忆下TCP/IP模型,从下到上分为:数据链路层.网络层.传输层.应用层,那么ARP到底属于哪一层?有人会说是网络层,但实际是属于数据链路层,只不过还要为网络层提供服务. A ...

  4. 使用SOCK_PACKET编写ARP请求程序的例子

    2010-01-14 11:06:35|  分类: linux program |  标签: |字号大中小 订阅 使用SOCK_PACKET编写ARP请求程序的例子 本节利用SOCK_PACKET套接 ...

  5. wireshark ARP抓包

    wireshark arp抓包 ARP 是借助 ARP 请求与 ARP 响应两种类型的包确定 MAC 地址. 1.主机会通过广播发送 ARP 请求,这个包中包含了想要知道的 MAC 地址的主机 IP ...

  6. ARP原理概述——基于WinPcap发送ARP请求数据包获取远程MAC地址

    ARP原理概述--基于WinPcap发送ARP请求数据包获取远程MAC地址 ARP协议 ARP概述 ARP工作原理 ARP数据包格式 编写程序发送ARP请求获取本机和远程IP的MAC 注意: ARP协 ...

  7. 如何理解lvs中DR模型的arp请求-arp_announce和arp_ignore

    arp_announce和arp_ignore 详细解说 版本V1.0 时间2012-06-16 版权GPL 作者itnihao 说明,本文档来自网络整理和个人理解综合整理 原文地址http://it ...

  8. Wireshark下载、Wireshark使用、Wireshark抓包、ARP抓包、ICMP抓包、TCP抓包、HTTP抓包

    Wireshark下载.Wireshark使用.Wireshark抓包.ARP抓包.ICMP抓包.TCP抓包.HTTP抓包 Wireshark下载 Wireshark抓包即快速定位数据包技巧 常见协议 ...

  9. 10.11 arping:发送arp请求

    arping命令 是用于发送arp请求到一个相邻主机的工具,arping使用arp数据包检查局域网内所有设备的硬件地址.  arping 命令的参数选项及说明 -c <次数>       ...

最新文章

  1. N-Case 律师事务所管理系统安装与卸载说明
  2. 活久见!如何看待北京理工大学某硕士生被指几乎一字不差地抄袭论文?
  3. Hyperledger Besu(3)“多用户架构”和“插件”
  4. CentOS7系统 yum 安装报错
  5. 【开启报名】云原生变革与效能技术沙龙 · 厦门站
  6. matlab sort对矩阵某一维进行排序并记录之前索引
  7. 怎么把4399小游戏的代码_25行代码带你爬取4399小游戏数据,看下童年的游戏是否还在...
  8. 查看oracle大页,在Oracle11.2.0.3.0上开启大页(hugepages)的详细解析
  9. html5显示特殊符号,HTML5特殊符号怎么显示-电脑自学网
  10. 谷粒商城 -- 项目环境搭建
  11. 杰理AD142A AD145A系列芯片的功能简介
  12. python 文本处理---英文文本预处理(简单易懂 全有注释)!!!!!使用正则表达式以及nltk库分词器双方法!
  13. 解决Android弹出Dialog小米手机需要打开“后台弹出界面”的权限问题
  14. Linux中对的tac命令
  15. 24位RGB颜色转换为16位RGB
  16. 一文学会回溯算法解题技巧
  17. jmeter--重新安装安装JDK
  18. arduino串口绘图_Arduino IDE开发环境串口绘图仪(Serial Plotter)使用方法简介
  19. 商业 v. s. 自由 ——W*ndows v. s. 现代UNIX
  20. a15仿生芯片和骁龙8gen1 哪个好

热门文章

  1. java获取焦点_[Java教程]dialog获取焦点
  2. python嵌套列表索引 index_Python:嵌套lis中元素的索引列表
  3. linux在cd后直接显示文件格式,Linux命令学习笔记之一目录与文件基本操作
  4. 从另一页面调用html代码_GNE v0.1正式发布:4行代码开发新闻网站通用爬虫
  5. spring cloud微服务_面试败给微服务?别怕,我带你一起手撕Dubbo,SpringBoot与Cloud...
  6. java spark dataset_Spark 2.0介绍:Dataset介绍和使用
  7. Java案例:文件切割与合并
  8. 《天天数学》连载12:一月十二日
  9. VB案例:素数判断与合数分解
  10. C ++ 指针 | this指针_2