Apple本身有一个专门ping IP的工具类,叫做SimplePing
/*! An object wrapper around the low-level BSD Sockets ping function.
* \details To use the class create an instance, set the delegate and call `-start`
* to start the instance on the current run loop. If things go well you'll soon get the
* `-simplePing:didStartWithAddress:` delegate callback. From there you can can call
* `-sendPingWithData:` to send a ping and you'll receive the
* `-simplePing:didReceivePingResponsePacket:sequenceNumber:` and
* `-simplePing:didReceiveUnexpectedPacket:` delegate callbacks as ICMP packets arrive.
*
* The class can be used from any thread but the use of any single instance must be
* confined to a specific thread and that thread must run its run loop.
*/
@interface SimplePing : NSObject
关于SimplePing的源码解读网上还是挺多的,感兴趣的小伙伴可以看一看iOS ping - SimplePing 源码解读,然后自己跑一下流程,不想看的同学可以直接看总结
- 解析
hostname
成IP地址- 发包
- 收包
但是SimplePing并没有告诉我们从发包到收包具体花了多久,所以需要我们自己去实现,此外,我们可能还需要同时去ping多个IP地址,这也是比较常见的需求之一。
基于以上两点需求,我在SimplePing的基础上封装了NENPingManager
内部实现原理如下:
获取IP地址数组后,先遍历派发任务,创建NENSinglePinger
,默认会ping3次,NENSinglePinger
会记录3次ping的结果,并取平均值
for (NSString *address in addressList) {
NENSinglePinger *singlePinger = [NENSinglePinger startWithHostName:address count:3 pingCallBack:^(NENPingItem *pingitem) {
// 省略
...
}];
[singlePingerArray addObject:singlePinger];
}
NENSinglePinger
是对SimplePing
的封装,相当于一个单体ping工具,内部实现了SimplePing的代理,在创建的时候,会启动SimplePing
的- (void)start
方法,如果一切正常,会调用- (void)simplePing:(SimplePing *)pinger didStartWithAddress:(NSData *)address
代理方法,在这个方法中会创建一个定时器,每隔0.4s会去发一次包,从发包开始会开始计时,记录每次发包的时间,如果在1s钟之内没有收到包,就调用- (void)timeOut
方法,按照延迟处理,延迟时间默认为1s,如果收到了包,就记录数据,并和开始的发包时间比较,并把数据回调给
NENPingManager
,当收到3次操作拉满的时候,就是收到包和timeout
的次数到达3次的时候,就操作终止,清楚掉定时器和其他的一些缓存数据。
tips: 如果没有效果,请确保
NENSinglePinger
是被强引用的,如果你用一个临时变量,可能还没开始请求就都被释放了。
Demo地址
喜欢的话就点个赞吧😊