大家好,今天给各位分享在iOS平台进行网络路径追踪与诊断的一些知识,其中也会对进行解释,文章篇幅可能偏长,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在就马上开始吧!
常用的ping 命令:
/**** 发送固定数量的数据包到目的地****/
ping -c 3 www.baidu.com //ping 百度发送3个数据包
/**** 设置两个数据包之间的等待时间****/
ping -i 5 www.baidu.com //两个数据包的时间间隔为5s
ping -i 0.1 www.baidu.com //两个数据包的时间间隔为0.1s
/**** 检查本地网络接口是否已启动并正在运行****/
ping 127.0.0.1 (linux: ping 0)
ping 本地主机
/**** 超级用户可以使用-f在几秒内发送数十万个数据包给主服务施加压力*****/
sudo ping -f www.baidu.com
/**** 让电脑发出蜂鸣声:当响应包到达目的地时,会发出声音****/
ping -a www.baidu.com
/**** 只打印ping 的摘要结果****/
ping -c 5 -q www.baidu.com
/**** 修改ping包(icmp包)大小****/
ping -s 100 -c 5 www.baidu.com 示例:
macdeiMac:PhoneNetSDK ethan$ ping www.baidu.com
PING www.a.shifen.com (61.135.169.121): 56 个数据字节
来自61.135.169.121: 的64 个字节icmp_seq=0 ttl=49 time=32.559 ms
来自61.135.169.121: 的64 个字节icmp_seq=1 ttl=49 time=32.413 ms
来自61.135.169.121: 的64 个字节icmp_seq=2 ttl=49 time=32.489 ms
^C
--- www.a.shifen.com ping 统计---
发送3 个数据包,接收3 个数据包,丢包率0.0%
往返最小/平均/最大/标准差=32.413/32.487/32.559/0.060 毫秒
macdeiMac:PhoneNetSDK ethan$ 分析上述结果:
发件人信息
www.a.shifen.com(61.135.169.121): 对域名进行自动DNS 解析56 数据字节: 向主机发送56 字节数据包。主机响应信息
icmp_seq: 响应数据包的序列号。 ttl: ip 数据报的ttl 值。 time: 请求往返时间。 64 bytes: 响应报文大小为64字节。统计汇总信息
0.0%丢包:总共发送了3个数据包。丢包率为0% min/avg/max=32.413/32.487/32.559:最小/平均/最大往返时间32.413/32.487/32.559TTL (Time to live) : IP 数据报告的生存时间,单位是跳数(hop)。例如64,每经过一个路由器,该值就减1。如果减少到0,则说明路由太长,无法找到目的主机的网络,因此数据包将被丢弃。
问:发送数据包时,为什么发送的是56 字节的数据包,而主机却回复64 字节的数据包?这里的56和64是同一个概念吗?
icmp
互联网控制消息协议(英文:Internet Control Message Protocol,缩写:ICMP)是互联网协议族的核心协议之一。它是TCP/IP协议族的一个子协议。它用于在TCP/IP网络中发送控制消息,并对通信环境中可能出现的各种问题提供反馈。通过这些信息,管理者可以对发生的问题做出反应。做出诊断,然后采取适当的措施来解决它。
控制消息包括:下次目的地不可达的时间、超时信息、重定向消息、时间戳请求和时间戳响应消息、回显请求和回显响应消息。
ICMP[1]依靠IP来完成其任务,它是IP的主要部分。它与TCP 和UDP 等传输协议有显着不同:它通常不用于在两点之间传输数据。它通常不被网络程序直接使用,除了ping 和traceroute 这两个特殊示例之外。 IPv4 中的ICMP 称为ICMPv4,IPv6 中的ICMP 称为ICMPv6。
icmp技术细节
CMP 是RFC 792 中定义的Internet 协议套件之一。通常用于返回错误信息或分析路由。 ICMP 错误消息始终包含返回给发送方的源数据。 ICMP 错误消息的一个示例是过期的TTL 值。每个路由器在转发数据报时都会将IP头中的TTL值减1。如果TTL值为0,则会向源地址返回“TTL在传输中过期”消息。每个ICMP 消息都直接封装在IP 数据包中,因此,与UDP 一样,ICMP 是不可靠的。
虽然ICMP包含在IP数据包中,但ICMP报文通常会被特殊处理,这与一般IP数据包的处理不同,而不是作为IP的子协议来处理。很多情况下,需要查看ICMP消息的内容,然后向最初生成IP数据包的程序,即导致ICMP消息传输的IP数据包发送适当的错误消息。
许多常用的工具都是基于ICMP 消息的。 Traceroute是通过发送包含特殊TTL的数据包,然后接收ICMP超报文和目的地不可达报文来实现的。 Ping 是使用ICMP 的“回显请求”(类别代码:8)和“回显回复”(类别代码:0)消息来实现的。
icmp报文结构
报头
ICMP 标头从IP 标头的第160 位开始(ip 标头20 字节)
imageType: ICMP类型,标识生成的错误消息Code:进一步划分了ICMP类型,该字段用于查找错误原因;例如,ICMP目标不可达类型可以将该位设置为1-15等以指示不同的含义。 Checksum : 校验和部分,该字段包含由ICMP 头和数据部分计算得出的数据,用于检查错误,其中该校验码字段的值视为0ID:该字段包含ID 值,在Echo Reply 中该字段应为在序列: 类型的消息中返回。该字段包含序列号。该字段也应该在Echo Reply 类型的消息中返回。
填充数据
。填充的数据紧跟在ICMP 标头之后(以8 位为一组)。
除了8 个8 字节标头之外,Linux ping 工具填充的ICMP 还会默认填充其他数据,使总大小为64 字节。除了八个八位字节标头之外,Windows 的ping.exe 填充的ICMP 还会默认填充其他数据,使总大小为40 字节。
ping
ping实现原理
Ping是测试另一台主机是否可达,现在已经成为常用的网络状态检查工具。该程序向远程主机发送ICMP 回显请求消息并等待返回ICMP 回显答复。
Ping 使用ICMP 协议,向目标主机发送icmp echo 请求消息。 ICMP协议规定目的主机必须向源主机返回ICMP回显响应消息。如果源主机在一定时间内收到响应,则认为该主机可达。大多数TCP/IP 实现直接支持内核中的Ping 服务器。 ICMP 回显请求和回显响应消息如下图所示。
成像原理:
镜像的原理是发送ICMP类型代码8的请求,收到请求的主机用ICMP类型代码0进行响应。通过计算ICMP响应报文的数量以及接收和发送的时间差来判断当前网络状态消息。这个往返时间的计算方法是:当ping命令发送ICMP报文时,它在ICMP报文中存储当前的时间值。当响应消息返回时,它使用当前时间值减去ICMP 消息数据中存储的值。发送请求的时间值以计算往返时间。 ping 返回接收到的数据报文本大小、TTL 值和往返时间。
利用wireshark查看ping
我在命令行中pingwww.baidu.com。显示结果如下:
imageimage如上图所示,icmp包的类型为8,为request请求; icmp包的类型为0,即回复。
计算机网络基础知识
TCP/IP协议栈与数据包封装
OSI 七层模型和TCP/IP 模型:
图片中两台计算机通过TCP/IP的通信过程如下:
图片传输层及以下机制由内核提供,应用层由用户进程提供,应用程序解释通信数据的含义,而传输层及以下处理通信细节,传递来自计算机的数据通过一定的路径。发送到另一台计算机。当应用层数据通过协议栈发送到网络时,每一层协议都必须添加一个数据头(header),称为封装(Encapsulation)。
TCP/IP数据包的封装:
目的主机收到数据包后,经过协议栈的每一层,最终到达应用程序。
图像以太网驱动程序首先根据以太网报头中的“上层协议”字段判断数据帧的负载是否是IP、ARP或RARP协议的数据报,然后将其交给相应的协议进行处理。如果是IP数据报,IP协议根据IP报头中的“上层协议”字段判断数据报的净荷是TCP、UDP、ICMP还是IGMP,然后交给相应的协议处理。如果是TCP报文段或UDP报文段,则TCP或UDP协议根据TCP报头或UDP报头中的“端口号”字段来决定应用层数据应该交给哪个用户进程。 IP地址是标识网络上不同主机的地址,端口号是标识同一主机上不同进程的地址。 IP 地址和端口号共同标识网络中的唯一进程。
注意,虽然IP、ARP和RARP数据报都需要以太网驱动程序来封装帧,但从功能上来说,ARP和RARP属于链路层,而IP属于网络层。虽然ICMP、IGMP、TCP和UDP数据都需要IP协议封装成数据报,但从功能上看,ICMP、IGMP和IP属于网络层,TCP和UDP属于传输层。
IP数据报格式
IPv4数据包格式如下:
图片关于标题长度:
根据IP数据报判断当前数据包是否为IPv4
version占4位,头长度占4位,version=4(IPv4),ipheader=20。
由于头长度以4字节为单位-version: 0100;标头长度:0101
获取版本: 0100 01010xFO(11110000)=01000000=0x40
获取报头长度: 0100 01010x0F(00001111)=0000 0101=5 4 bytes=20 Byte
ping实现(c++oc)
技术预研与构思
根据ping 结果,需要解决以下问题:
macdeiMac:PhoneNetSDK ethan$ ping www.baidu.com
PING www.a.shifen.com (61.135.169.121): 56 个数据字节
来自61.135.169.121: 的64 个字节icmp_seq=0 ttl=49 time=32.559 ms
来自61.135.169.121: 的64 个字节icmp_seq=1 ttl=49 time=32.413 ms
来自61.135.169.121: 的64 个字节icmp_seq=2 ttl=49 time=32.489 ms
^C
--- www.a.shifen.com ping 统计---
发送3 个数据包,接收3 个数据包,丢包率0.0%
往返最小/平均/最大/标准差=32.413/32.487/32.559/0.060 毫秒
macdeiMac:PhoneNetSDK ethan$DNS解析(域名-ip) 本地终端收到的每个icmp数据包来自哪台主机icmp_seqttltime 上述问题的解决方案如下:
DNS分析:套接字支持本地终端收到的每个icmp数据包来自哪个主机: sourceicmp_seq: ip数据包中的序号ttl: ip数据包中的time to livetime: 发送数据包和接收数据包的时间差
具体实现
IP数据包定义:
typedef 结构PNetIPHeader {
uint8_t 版本和标题长度;
uint8_t 差异化服务;
uint16_t 总长度;
uint16_t标识;
uint16_t flagsAndFragmentOffset;
uint8_t 生存时间;
uint8_t 协议;
uint16_t headerChecksum;
uint8_t 源地址[4];
uint8_t 目的地地址[4];
//选项.
//数据.
}PNetIPHeader;ICMP数据包定义:
/*
使用Linux风格。总计64B
*/
typedef 结构UICMPPacket
{
uint8_t 类型;
uint8_t 代码;
uint16_t 校验和;
uint16_t 标识符;
uint16_t 序列;
字符填充[56]; //数据
}UICMP数据包;构造ICMP数据包:
+ (UICMPPacket *)constructPacketWithSeq:(uint16_t)seq 和Identifier:(uint16_t)identifier
{
UICMPPacket *packet=(UICMPPacket *)malloc(sizeof(UICMPPacket));
数据包类型=ENU_U_ICMPType_EchoRequest;
数据包代码=0;
数据包校验和=0;
数据包标识符=OSSwapHostToBigInt16(标识符);
packet-seq=OSSwapHostToBigInt16(seq);
memset(数据包填充, 65, 56);
packet-checksum=[self in_cksumWithBuffer:packet andSize:sizeof(UICMPPacket)];
返回数据包;
}发送icmp数据包:
UICMPPacket *packet=[PhoneNetDiagnosisHelper ConstructionPacketWithSeq:index andIdentifier:identifier];
_sendDate=[NSDate 日期];
ssize_t 发送=sendto(socket_client, packet, sizeof(UICMPPacket), 0, (struct sockaddr *)remote_addr, (socklen_t)sizeof(struct sockaddr));
如果(发送0){
log4cplus_warn("PhoneNetPing", "ping %s , 发送icmp 数据包错误.n",[self.host UTF8String]);
}接收icmp数据包:
size_t bytesRead=recvfrom(socket_client, buffer, 65535, 0, (struct sockaddr *)ret_addr, addrLen);
if ((int)bytesRead 0) {
[自我记者PingResWithSorceIp:self.host ttl:0 timeMillSecond:0 seq:0 icmpId:0 dataSize:0 pingStatus:PhoneNetPingStatusDidTimeout];
解析度=是;
}否则if(bytesRead==0){
log4cplus_warn("PhoneNetPing", "ping %s ,接收icmp数据包错误, bytesRead=0",[self.host UTF8String]);
}别的{
if ([PhoneNetDiagnosisHelper isValidPingResponseWithBuffer:(char *)buffer len:(int)bytesRead]) {
UICMPPacket *icmpPtr=(UICMPPacket *)[PhoneNetDiagnosisHelper icmpInpacket:(char *)buffer andLen:(int)bytesRead];
int seq=OSSwapBigToHostInt16(icmpPtr-seq);
NSTimeInterval 持续时间=[[NSDate 日期] timeIntervalSinceDate:_sendDate];
int ttl=((PNetIPHeader *)buffer)-timeToLive;
int size=(int)(bytesRead-sizeof(PNetIPHeader));
NSString *sorceIp=self.host;
//NSLog(@"PhoneNetPing, ping %@ , 接收icmp 数据包.n",self.host );
[self reportsPingResWithSorceIp:sorceIp ttl:ttl timeMillSecond:duration*1000 seq:seq icmpId:OSSwapBigToHostInt16(icmpPtr-identifier) dataSize:size pingStatus:PhoneNetPingStatusDidReceivePack et ];
解析度=是;
}从接收的缓冲区中分离icmp 数据包:
/* 从ipv4 数据包中解析icmp */
+ (char *)icmpInpacket:(char *)packet 和Len:(int)len
{
if (len (sizeof(PNetIPHeader) + sizeof(UICMPPacket))) {
返回空值;
}
const struct PNetIPHeader *ipPtr=(const PNetIPHeader *)packet;
if ((ipPtr-versionAndHeaderLength0xF0) !=0x40 //IPv4
||
ipPtr-协议!=1) { //ICMP
返回空值;
}
size_t ipHeaderLength=(ipPtr-versionAndHeaderLength0x0F) * sizeof(uint32_t);
if (len ipHeaderLength + sizeof(UICMPPacket)) {
返回空值;
}
返回(char *)数据包+ ipHeaderLength;
}验证收到的icmp数据包:
+ (BOOL)isValidPingResponseWithBuffer:(char *)缓冲区len:(int)len
{
UICMPPacket *icmpPtr=(UICMPPacket *)[self icmpInpacket:buffer andLen:len];
如果(icmpPtr==NULL){
返回否;
}
uint16_t receiveChecksum=icmpPtr-checksum;
icmpPtr 校验和=0;
uint16_t计算校验和=[self in_cksumWithBuffer:icmpPtr andSize:len-((char*)icmpPtr - 缓冲区)];
返回收到的校验和==计算的校验和
icmpPtr 类型==ENU_U_ICMPType_EchoReplay
icmpPtr 代码==0
OSSwapBigToHostInt16(icmpPtr-identifier)=KPingIcmpIdBeginNum;
}
TCP ping
当某些服务器禁止ping时,可以选择TCP ping。
TCP ping原理
映像通过与目标主机及其端口建立TCP 连接来计算连接时间。
traceroute
traceroute命令
/**** 设置每条路由发送的数据包数量****/
traceroute -q 5 baidu.com
/****设置最大路由跳数****/
traceroute -m 5 baidu.com
/**** 无DNS 解析****/
traceroute -n baidu.com
/**** 绕过路由表,直接发送到目标设备****/
traceroute -r baidu.com
/**** 使用ICMP 数据包代替UDP 数据包****/
traceroute -I baidu.com
traceroute原理
tacceroute 通过增加生存时间(TTL)值来实现其功能。每当icmp
包经过一个路由器时,其存活时间值就会减1,当其存活时间为0时,路由器便会取消包发送,并发送一个ICMP TTL封包给原封包发出者。 imagetraceroute过程
主叫方首先发出TTL = 1 的数据包,第一个路由器将 TTL 减1得0后就不再继续转发此数据包,而是返回一个ICMP超时报文,主叫方从超时报文中即可提取出数据包所经过的第一个路由器的地址。然后又发出一个TTL=2的ICMP数据包,可获得第二个路由器的地址,依次增加TTL便获取了沿途所有路由器位地址。 需要注意的是,并不是所有路由器都会如实返回ICMP超时报文。出于安全性考虑,大多数防火墙以及启动了防火墙功能的路由器缺省配置为不返回各种ICMP报文,其路由器或交换机也可被管理员主动修改配置变为不返回ICMP报文。因此Traceroute程序不一定能拿全所有沿途路由器地址。所以当某个TTL值的数据包得不到响应是,并不能停止这一追踪过程,程序仍然会把TTL递增而发出下一个数据包。一直达到预设或用于参数制定的追踪限制时才结束追踪。 依据上述原理,利用了UDP数据包的Traceroute程序在数据包到达真正的目的主机时,就可能因为该主机没有提供UDP服务而简单将数据包丢弃,并不返回任何信息。为了解决这个问题,Traceroute故意使用了一个大于30000的端口号,因UDP协议规定端口号必须小于30000,所以目标主机收到数据包后唯一能做的事就是返回一个"端口不可达"的ICMP报文,于是主叫方就将端口不可达报文当做跟踪结束标志。利用wireshark查看traceroute
我在命令行中traceroutewww.baidu.com以下是显示结果: image如上图所示,UDP请求,第一个请求的端口是33435 , 接下来的UDP请求,端口会递增。 当到达目的地址时,目的地址会replay类型为3的包. image如上图所示,是路由器返回的ICMP包,type是11。UDP traceroute的实现
发送udp包,接收ip+icmp包,过滤route ip计算时间。 https://github.com/mediaios/net-diagnosis/tree/master/PhoneNetSDK/PhoneNetSDK/udptracertUDP traceroute存在的问题
使用 UDP 的 traceroute,失败还是比较常见的。这常常是由于,在运营商的路由器上,UDP 与 ICMP 的待遇大不相同。为了利于 troubleshooting,ICMP 的request 和 replay 是不会封的,而 UDP 则不同。UDP 常被用来做网络攻击,因为 UDP 无需连接,因而没有任何状态约束它,比较方便攻击者伪造源 IP、伪造目的端口发送任意多的 UDP 包,长度自定义。所以运营商为安全考虑,对于 UDP 端口常常采用白名单 ACL,就是只有 ACL 允许的端口才可以通过,没有明确允许的则统统丢弃。比如允许 DNS/DHCP/SNMP 等。icmp traceroute
发送icmp包,类型为8,每个路由返回的icmp包类型是11的超时包,当到达目的地址时,目的地址会replay类型为0的包 imageicmp traceroute的实现
https://github.com/mediaios/net-diagnosis/tree/master/PhoneNetSDK/PhoneNetSDK/utracertnet-diagnosis(ios平台下网络诊断SDK)
net-diagnosis是ios平台下的网络诊断SDK,提供的功能有: pingtcp pingtracerouteicmp traceroutenslookupport scan项目地址:github好了,关于在iOS平台进行网络路径追踪与诊断和的问题到这里结束啦,希望可以解决您的问题哈!
【在iOS平台进行网络路径追踪与诊断】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
这真是个好话题!我一直想知道如何在iPhone上测试网络连接状况。
有9位网友表示赞同!
学习新的iOS技术啊,挺棒的!
有5位网友表示赞同!
我以前是用电脑来做Ping和traceroute的,手机端也是很有用的功能。
有9位网友表示赞同!
对开发者来说,了解网络性能至关重要,这篇文章应该很实用。
有9位网友表示赞同!
希望文章能讲得详细一点,更容易理解。
有11位网友表示赞同!
有没有iOS应用程序可以实现这些功能?
有15位网友表示赞同!
我感觉这样的功能对调试网络问题相当有用。
有20位网友表示赞同!
不知道苹果会不会官方支持这些功能呢?
有18位网友表示赞同!
学习这个技能感觉很有成就感!
有15位网友表示赞同!
期待看到关于实践操作的部分。
有13位网友表示赞同!
可以分享一下相关的代码示例吗?
有16位网友表示赞同!
用手机测试网络感觉还是挺简单的,方便快捷。
有15位网友表示赞同!
这篇文章能否涵盖一些常见的问题和解决方案?
有7位网友表示赞同!
iOS平台确实越来越强大,功能越来越完善了。
有14位网友表示赞同!
学习新的技术总是一件令人兴奋的事情。
有20位网友表示赞同!
期待看到更多关于iOS开发的优秀内容。
有9位网友表示赞同!
这篇文章能帮到很多想调试网络问题的开发者。
有5位网友表示赞同!
我对技术的应用范围越来越感兴趣,手机上实现这些功能也很酷。
有20位网友表示赞同!
我相信这篇文章会吸引很多人的关注。
有12位网友表示赞同!
感谢作者分享这组精彩的技术内容!
有8位网友表示赞同!
学习完之后我可以自己试试用ios平台做Ping 和 traceroute 了!
有6位网友表示赞同!