iOS 流量监控分析,从零基础到精通,收藏这篇就够了!

PHP实现跨域COOKIE(附完整源码) 阅读详情

作者 | 小鱼周凌宇,目前在饿了么物流iOS 组,主要工作内容蜂鸟骑手 app 和一些组内框架相关,业余喜欢日番,画画,
微博 | https://weibo.com/coderfish

由于骑手不能随时处在有 WIFI 的状态,流量变成了很敏感的问题,为了精确到每个 API 的流量,进行针对性的优化,开始在我们的 APM 中添加流量监控功能。
本文将记录自己做流量监控方面的总结。其中包括了非常多的踩坑经验,和现有一些方案的缺陷分析,对我来说是一个非常有意义的过程。

干货预警🤣请做好读大量代码的准备😂😂😂

一、资料收集

就目前来说,各家大厂基本都有自己的 APM(包括我们公司其实之前也有一套 APM,但是由于各个事业部的需求不同,尚不能完全满足物流平台的需要)但各家大厂目前开源的 APM 项目却不多,当然也可能是由于各家的业务场景差异比较大且对数据的后续处理不同。
所以本次在查阅资料阶段,没有太多的源码可选参考,但有不少文章。
以下是一些本次开发过程中参考的文章和开源库:

• iOS-Monitor-Platform[1]
• GodEye[2]
• NetworkEye[3]
• 移动端性能监控方案Hertz[4]
• 使用NSURLProtocol注意的一些问题[5]
• iOS 开发中使用 NSURLProtocol 拦截 HTTP 请求[6]
• 获取NSURLResponse的HTTPVersion[7]

但以上这些资料对我们的需求都有不足之处:

1. Request 和 Response 记在同一条记录

在实际的网络请求中 Request 和 Response 不一定是成对的,如果网络断开、或者突然关闭进程,都会导致不成对现象,如果将 Request 和 Response 记录在同一条数据,将会对统计造成偏差

2. 上行流量记录不精准

主要的原因有三大类:

• 直接忽略了 Header 和 Line 部分
• 忽略了 Cookie 部分,实际上,臃肿的 Cookie 也是消耗流量的一部分
• body 部分的字节大小计算直接使用了 HTTPBody.length 不够准确

3. 下行流量记录不精准

主要原因有:

• 直接忽略了 Header 和 Status-Line 部分
• body 部分的字节大小计算直接使用了 expectedContentLength 不够准确
• 忽略了 gzip 压缩,在实际网络编程中,往往都使用了 gzip 来进行数据压缩,而系统提供的一些监听方法,返回的 NSData 实际是解压过的,如果直接统计字节数会造成大量偏差

后文将详细讲述。

二、需求

先简单罗列我们的需求:

• Request 基本信息记录
• 上行流量
• Reponse 基本信息记录
• 下行流量
• 数据归类:按照 host 和 path 归类,一条记录记载改 host/path 的 Request 记录数,Response 记录数,Reqeust 总流量(上行流量),Reponse 总流量(下行流量)

我们的侧重点是流量统计,为了方便分析 APP 使用中哪些 API 消耗流量多。所以对上行、下行流量都需要尽量准确记录。

最终的数据库表展示:

type 字段表示的是『该条记录是 Request 还是 Response』,几个 length 分别记录了流量的各个细节,包括:总字节数、Line 字节数、Header 字节数、Body 字节数。

最后的界面展示类似于:

三、分析现有资料

现在分析一下上面收集到的资料有哪些不足之处。

GodEye[2] | NetworkEye[3]:

NetworkEye 是 GodEye 的一部分,可以单独拆出来使用的网络监控库。
查阅两者的源码后发现,NetworkEye

  1. 仅仅记录了 Reponse 的流量

  2. 通过 expectedContentLength 记录是不准确的(后面将会说到)

  3. 仅仅记录了总和,这对我们来说是无意义的,不能分析出哪条 API 流量使用多

移动端性能监控方案Hertz[4]:

美团的文章中展示几个代码片段:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection  
{  
    [self.client URLProtocolDidFinishLoading:self];  
  
    self.data = nil;  
    if (connection.originalRequest) {  
        WMNetworkUsageDataInfo *info = [[WMNetworkUsageDataInfo alloc] init];  
        self.connectionEndTime = [[NSDate date] timeIntervalSince1970];  
        info.responseSize = self.responseDataLength;  
        info.requestSize = connection.originalRequest.HTTPBody.length;  
        info.contentType = [WMNetworkUsageURLProtocol getContentTypeByURL:connection.originalRequest.URL andMIMEType:self.MIMEType];  
    [[WMNetworkMeter sharedInstance] setLastDataInfo:info];  
    [[WMNetworkUsageManager sharedManager] recordNetworkUsageDataInfo:info];  
}  

在 connectionDidFinishLoading 中记录了整个网络请求结束的时间、 response 数据大小、request 数据大小以及一些其他数据。

总体来说是比较详细的,但是这里并没有给出 self.responseDataLength 的具体逻辑,另外 connection.originalRequest.HTTPBody.length 仅仅是 Request body 的大小。

iOS-Monitor-Platform[1]:

这篇文章比较详细的介绍了整个 APM 制作的过程,贴出了很多代码段,应该说非常详细也极具参考价值。

在流量部分,也分别针对了上行流量、下行流量进行了区分,但其中:

  1. 没有处理 gzip 压缩情况

  2. 对 Header 计算大小的方式是 Dictionary 转 NSData,然而实际上头部并不是 Json 格式(这块我觉得很迷,因为作者特意展示了 HTTP 报文组成)

四、动手自己做

HTTP 报文

为了更好的让大家了解 HTTP 流量计算的一些关键信息,首先要了解 HTTP 报文的组成。

再来随便抓个包具体看看:

iOS 下的网络监控

这块我采用的大家耳熟能详的 NSURLProtocol,NSURLProtocol 方式除了通过 CFNetwork 发出的网络请求,全部都可以拦截到。

Apple 文档[8]中对 NSURLProtocol 有非常详细的描述和使用介绍

An abstract class that handles the loading of protocol-specific URL data.

如果想更详细的了解 NSURLProtocol,也可以看大佐的_这篇文章_[9]

在每一个 HTTP 请求开始时,URL 加载系统创建一个合适的 NSURLProtocol 对象处理对应的 URL 请求,而我们需要做的就是写一个继承自 NSURLProtocol 的类,并通过 - registerClass: 方法注册我们的协议类,然后 URL 加载系统就会在请求发出时使用我们创建的协议对象对该请求进行处理。

NSURLProtocol 是一个抽象类,需要做的第一步就是集成它,完成我们的自定义设置。

创建自己的 DMURLProtocol,为它添加几个属性并实现相关接口:

@interface DMURLProtocol() <NSURLConnectionDelegate, NSURLConnectionDataDelegate>  
  
@property (nonatomic, strong) NSURLConnection *connection;  
@property (nonatomic, strong) NSURLRequest *dm_request;  
@property (nonatomic, strong) NSURLResponse *dm_response;  
@property (nonatomic, strong) NSMutableData *dm_data;  
  
@end  

canInitWithRequest & canonicalRequestForRequest:

static NSString *const DMHTTP = @"LPDHTTP";  

+ (BOOL)canInitWithRequest:(NSURLRequest *)request {  
    if (![request.URL.scheme isEqualToString:@"http"]) {  
        return NO;  
    }  
    // 拦截过的不再拦截  
    if ([NSURLProtocol propertyForKey:LPDHTTP inRequest:request] ) {  
        return NO;  
    }  
    return YES;  
}  

+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {  
    NSMutableURLRequest *mutableReqeust = [request mutableCopy];  
    [NSURLProtocol setProperty:@YES  
                        forKey:DMHTTP  
                     inRequest:mutableReqeust];  
    return [mutableReqeust copy];  
}  

startLoading:

- (void)startLoading {  
    NSURLRequest *request = [[self class] canonicalRequestForRequest:self.request];  
    self.connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];  
    self.dm_request = self.request;  
}  

didReceiveResponse:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {  
    [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed];  
    self.dm_response = response;  
}  

didReceiveData:

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {  
    [self.client URLProtocol:self didLoadData:data];  
    [self.dm_data appendData:data];  
}  

以上部分是为了在单次 HTTP 请求中记录各个所需要属性。

记录 Response 信息

前面的代码实现了在网络请求过程中为 dm_response 和 dm_data 赋值,那么在 stopLoading 方法中,就可以分析 dm_response 和 dm_data 对象,获取下行流量等相关信息。

需要说明的是,如果需要获得非常精准的流量,一般来说只有通过 Socket 层获取是最准确的,因为可以获取包括握手、挥手的数据大小。当然,我们的目的是为了分析 App 的耗流量 API,所以仅从应用层去分析也基本满足了我们的需要。

上文中说到了报文的组成,那么按照报文所需要的内容获取。

Status Line

非常遗憾的是 NSURLResponse 没有接口能直接获取报文中的 Status Line,甚至连 HTTP Version 等组成 Status Line 内容的接口也没有。

最后,我通过转换到 CFNetwork 相关类,才拿到了 Status Line 的数据,这其中可能涉及到了读取私有 API

这里我为 NSURLResponse 添加了一个扩展:NSURLResponse+DoggerMonitor,并为其添加 statusLineFromCF 方法

typedef CFHTTPMessageRef (*DMURLResponseGetHTTPResponse)(CFURLRef response);  
  
- (NSString *)statusLineFromCF {  
    NSURLResponse *response = self;  
    NSString *statusLine = @"";  
    // 获取CFURLResponseGetHTTPResponse的函数实现  
    NSString *funName = @"CFURLResponseGetHTTPResponse";  
    DMURLResponseGetHTTPResponse originURLResponseGetHTTPResponse =  
    dlsym(RTLD_DEFAULT, [funName UTF8String]);  
  
    SEL theSelector = NSSelectorFromString(@"_CFURLResponse");  
    if ([response respondsToSelector:theSelector] &&  
        NULL != originURLResponseGetHTTPResponse) {  
        // 获取NSURLResponse的_CFURLResponse  
        CFTypeRef cfResponse = CFBridgingRetain([response performSelector:theSelector]);  
        if (NULL != cfResponse) {  
            // 将CFURLResponseRef转化为CFHTTPMessageRef  
            CFHTTPMessageRef messageRef = originURLResponseGetHTTPResponse(cfResponse);  
            statusLine = (__bridge_transfer NSString *)CFHTTPMessageCopyResponseStatusLine(messageRef);  
            CFRelease(cfResponse);  
        }  
    }  
    return statusLine;  
}  

通过调用私有 API _CFURLResponse 获得 CFTypeRef 再转换成 CFHTTPMessageRef,获取 Status Line。

再将其转换成 NSData 计算字节大小:

- (NSUInteger)dm_getLineLength {  
    NSString *lineStr = @"";  
    if ([self isKindOfClass:[NSHTTPURLResponse class]]) {  
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)self;  
        lineStr = [self statusLineFromCF];  
    }  
    NSData *lineData = [lineStr dataUsingEncoding:NSUTF8StringEncoding];  
    return lineData.length;  
}  

Header

通过 httpResponse.allHeaderFields 拿到 Header 字典,再拼接成报文的 key: value 格式,转换成 NSData 计算大小:

- (NSUInteger)dm_getHeadersLength {  
    NSUInteger headersLength = 0;  
    if ([self isKindOfClass:[NSHTTPURLResponse class]]) {  
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)self;  
        NSDictionary<NSString *, NSString *> *headerFields = httpResponse.allHeaderFields;  
        NSString *headerStr = @"";  
        for (NSString *key in headerFields.allKeys) {  
            headerStr = [headerStr stringByAppendingString:key];  
            headerStr = [headerStr stringByAppendingString:@": "];  
            if ([headerFields objectForKey:key]) {  
                headerStr = [headerStr stringByAppendingString:headerFields[key]];  
            }  
            headerStr = [headerStr stringByAppendingString:@"\n"];  
        }  
        NSData *headerData = [headerStr dataUsingEncoding:NSUTF8StringEncoding];  
        headersLength = headerData.length;  
    }  
    return headersLength;  
}  

Body

对于 Body 的计算,上文看到有些文章里采用的 expectedContentLength 或者去 NSURLResponse 对象的 allHeaderFields 中获取 Content-Length 值,其实都不够准确。

首先 API 文档中对 expectedContentLength 也有介绍是不准确的:

其次,HTTP 1.1 标准里也有介绍 Content-Length 字段不一定是每个 Response 都带有的,最重要的是,Content-Length 只是表示 Body 部分的大小。

我的方式是,在前面代码中有写到,在 didReceiveData 中对 dm_data 进行了赋值

didReceiveData:

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {  
    [self.client URLProtocol:self didLoadData:data];  
    [self.dm_data appendData:data];  
}  

那么在 stopLoading 方法中,就可以拿到本次网络请求接收到的数据。
但需要注意对 gzip 情况进行区别分析。我们知道 HTTP 请求中,客户端在发送请求的时候会带上 Accept-Encoding,这个字段的值将会告知服务器客户端能够理解的内容压缩算法。而服务器进行相应时,会在 Response 中添加 Content-Encoding 告知客户端选中的压缩算法。

所以,我们在 stopLoading 中获取 Content-Encoding,如果使用了 gzip,则模拟一次 gzip 压缩,再计算字节大小:

- (void)stopLoading {  
    [self.connection cancel];  
  
    DMNetworkTrafficLog *model = [[DMNetworkTrafficLog alloc] init];  
    model.path = self.request.URL.path;  
    model.host = self.request.URL.host;  
    model.type = DMNetworkTrafficDataTypeResponse;  
    model.lineLength = [self.dm_response dm_getLineLength];  
    model.headerLength = [self.dm_response dm_getHeadersLength];  
    if ([self.dm_response isKindOfClass:[NSHTTPURLResponse class]]) {  
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)self.dm_response;  
        NSData *data = self.dm_data;  
        if ([[httpResponse.allHeaderFields objectForKey:@"Content-Encoding"] isEqualToString:@"gzip"]) {  
            // 模拟压缩  
            data = [self.dm_data gzippedData];  
        }  
        model.bodyLength = data.length;  
    }  
    model.length = model.lineLength + model.headerLength + model.bodyLength;  
    [model settingOccurTime];  
    [[DMDataManager defaultDB] addNetworkTrafficLog:model];  
}  

这里 gzippedData 参考_这个库的内容_[9]

[[DMDataManager defaultDB] addNetworkTrafficLog:model]; 是调用持久化层的代码将数据落库。

记录 Resquest 信息

Line

很遗憾,对于NSURLRequest 我没有像 NSURLReponse 一样幸运的找到私有接口将其转换成 CFNetwork 相关数据,但是我们很清楚 HTTP 请求报文 Line 部分的组成,所以我们可以添加一个方法,获取一个经验 Line。

同样为 NSURLReques 添加一个扩展:NSURLRequest+DoggerMonitor

- (NSUInteger)dgm_getLineLength {  
    NSString *lineStr = [NSString stringWithFormat:@"%@ %@ %@\n", self.HTTPMethod, self.URL.path, @"HTTP/1.1"];  
    NSData *lineData = [lineStr dataUsingEncoding:NSUTF8StringEncoding];  
    return lineData.length;  
}  

Header

Header 这里有一个非常大的坑。

request.allHTTPHeaderFields 拿到的头部数据是有很多缺失的,这块跟业内朋友交流的时候,发现很多人都没有留意到这个问题。

缺失的部分不仅仅是上面一篇文章中说到的 Cookie。

如果通过 Charles 抓包,可以看到,会缺失包括但不仅限于以下字段:

  1. Accept

  2. Connection

  3. Host

这个问题非常的迷,同时由于无法转换到 CFNetwork 层,所以一直拿不到准确的 Header 数据。

最后,我在 so 上也找到了两个相关问题,供大家参考

NSUrlRequest: where an app can find the default headers for HTTP request?[10]

NSMutableURLRequest, cant access all request headers sent out from within my iPhone program[11]

两个问题的回答基本表明了,如果你是通过 CFNetwork 来发起请求的,才可以拿到完整的 Header 数据。

所以这块只能拿到大部分的 Header,但是基本上缺失的都固定是那几个字段,对我们流量统计的精确度影响不是很大。

那么主要就针对 cookie 部分进行补全:

- (NSUInteger)dgm_getHeadersLengthWithCookie {  
    NSUInteger headersLength = 0;  
  
    NSDictionary<NSString *, NSString *> *headerFields = self.allHTTPHeaderFields;  
    NSDictionary<NSString *, NSString *> *cookiesHeader = [self dgm_getCookies];  
  
    // 添加 cookie 信息  
    if (cookiesHeader.count) {  
        NSMutableDictionary *headerFieldsWithCookies = [NSMutableDictionary dictionaryWithDictionary:headerFields];  
        [headerFieldsWithCookies addEntriesFromDictionary:cookiesHeader];  
        headerFields = [headerFieldsWithCookies copy];  
    }  
    NSLog(@"%@", headerFields);  
    NSString *headerStr = @"";  
  
    for (NSString *key in headerFields.allKeys) {  
        headerStr = [headerStr stringByAppendingString:key];  
        headerStr = [headerStr stringByAppendingString:@": "];  
        if ([headerFields objectForKey:key]) {  
            headerStr = [headerStr stringByAppendingString:headerFields[key]];  
        }  
        headerStr = [headerStr stringByAppendingString:@"\n"];  
    }  
    NSData *headerData = [headerStr dataUsingEncoding:NSUTF8StringEncoding];  
    headersLength = headerData.length;  
    return headersLength;  
}  

- (NSDictionary<NSString *, NSString *> *)dgm_getCookies {  
    NSDictionary<NSString *, NSString *> *cookiesHeader;  
    NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];  
    NSArray<NSHTTPCookie *> *cookies = [cookieStorage cookiesForURL:self.URL];  
    if (cookies.count) {  
        cookiesHeader = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];  
    }  
    return cookiesHeader;  
}  

body

最后是 body 部分,这里也有个坑。通过 NSURLConnection 发出的网络请求 resquest.HTTPBody 拿到的是 nil。

需要转而通过 HTTPBodyStream 读取 stream 来获取 request 的 Body 大小。

- (NSUInteger)dgm_getBodyLength {  
    NSDictionary<NSString *, NSString *> *headerFields = self.allHTTPHeaderFields;  
    NSUInteger bodyLength = [self.HTTPBody length];  
  
    if ([headerFields objectForKey:@"Content-Encoding"]) {  
        NSData *bodyData;  
        if (self.HTTPBody == nil) {  
            uint8_t d[1024] = {0};  
            NSInputStream *stream = self.HTTPBodyStream;  
            NSMutableData *data = [[NSMutableData alloc] init];  
            [stream open];  
            while ([stream hasBytesAvailable]) {  
                NSInteger len = [stream read:d maxLength:1024];  
                if (len > 0 && stream.streamError == nil) {  
                    [data appendBytes:(void *)d length:len];  
                }  
            }  
            bodyData = [data copy];  
            [stream close];  
        } else {  
            bodyData = self.HTTPBody;  
        }  
        bodyLength = [[bodyData gzippedData] length];  
    }  
  
    return bodyLength;  
}  

落库

最后在 DMURLProtocol 的 - (nullable NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(nullable NSURLResponse *)response; 方法中对 resquest 调用报文各个部分大小方法后落库:

-(NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response {  
    if (response != nil) {  
        self.dm_response = response;  
        [self.client URLProtocol:self wasRedirectedToRequest:request redirectResponse:response];  
    }  
  
    DMNetworkTrafficLog *model = [[DMNetworkTrafficLog alloc] init];  
    model.path = request.URL.path;  
    model.host = request.URL.host;  
    model.type = DMNetworkTrafficDataTypeRequest;  
    model.lineLength = [connection.currentRequest dgm_getLineLength];  
    model.headerLength = [connection.currentRequest dgm_getHeadersLengthWithCookie];  
    model.bodyLength = [connection.currentRequest dgm_getBodyLength];  
    model.length = model.lineLength + model.headerLength + model.bodyLength;  
    [model settingOccurTime];  
    [[DMDataManager defaultDB] addNetworkTrafficLog:model];  
    return request;  
}  

针对 NSURLSession 的处理

直接使用 DMURLProtocol 并 registerClass 并不能完整的拦截所有网络请求,因为通过 NSURLSession 的 sharedSession 发出的请求是无法被 NSURLProtocol 代理的。

我们需要让 [NSURLSessionConfiguration defaultSessionConfiguration].protocolClasses 的属性中也设置我们的 DMURLProtocol,这里通过 swizzle,置换 protocalClasses 的 get 方法:

编写一个 DMURLSessionConfiguration

#import <Foundation/Foundation.h>  
  
@interface DMURLSessionConfiguration : NSObject  
  
@property (nonatomic,assign) BOOL isSwizzle;  
+ (DMURLSessionConfiguration *)defaultConfiguration;  
- (void)load;  
- (void)unload;  
  
@end  

#import "DMURLSessionConfiguration.h"  
#import <objc/runtime.h>  
#import "DMURLProtocol.h"  
#import "DMNetworkTrafficManager.h"  
  
@implementation DMURLSessionConfiguration  
  
+ (DMURLSessionConfiguration *)defaultConfiguration {  
    static DMURLSessionConfiguration *staticConfiguration;  
    static dispatch_once_t onceToken;  
    dispatch_once(&onceToken, ^{  
        staticConfiguration=[[DMURLSessionConfiguration alloc] init];  
    });  
    return staticConfiguration;  
      
}  
  
- (instancetype)init {  
    self = [super init];  
    if (self) {  
        self.isSwizzle = NO;  
    }  
    return self;  
}  
  
- (void)load {  
    self.isSwizzle = YES;  
    Class cls = NSClassFromString(@"__NSCFURLSessionConfiguration") ?: NSClassFromString(@"NSURLSessionConfiguration");  
    [self swizzleSelector:@selector(protocolClasses) fromClass:cls toClass:[self class]];  
      
}  
  
- (void)unload {  
    self.isSwizzle=NO;  
    Class cls = NSClassFromString(@"__NSCFURLSessionConfiguration") ?: NSClassFromString(@"NSURLSessionConfiguration");  
    [self swizzleSelector:@selector(protocolClasses) fromClass:cls toClass:[self class]];  
}  
  
- (void)swizzleSelector:(SEL)selector fromClass:(Class)original toClass:(Class)stub {  
    Method originalMethod = class_getInstanceMethod(original, selector);  
    Method stubMethod = class_getInstanceMethod(stub, selector);  
    if (!originalMethod || !stubMethod) {  
        [NSException raise:NSInternalInconsistencyException format:@"Couldn't load NEURLSessionConfiguration."];  
    }  
    method_exchangeImplementations(originalMethod, stubMethod);  
}  
  
- (NSArray *)protocolClasses {  
    // DMNetworkTrafficManager 中的 protocolClasses 可以给使用者设置自定义的 protocolClasses  
    return [DMNetworkTrafficManager manager].protocolClasses;  
}  
  
@end  

这样,我们写好了方法置换,在执行过该类单例的 load 方法后,[NSURLSessionConfiguration defaultSessionConfiguration].protocolClasses 拿到的将会是我们设置好的 protocolClasses。

如此,我们再为 DMURLProtocol 添加 start 和 stop 方法,用于启动网络监控和停止网络监控:

+ (void)start {  
    DMURLSessionConfiguration *sessionConfiguration = [DMURLSessionConfiguration defaultConfiguration];  
    for (id protocolClass in [DMNetworkTrafficManager manager].protocolClasses) {  
        [NSURLProtocol registerClass:protocolClass];  
    }  
    if (![sessionConfiguration isSwizzle]) {  
        // 设置交换  
        [sessionConfiguration load];  
    }  
}  
  
+ (void)end {  
    DMURLSessionConfiguration *sessionConfiguration = [DMURLSessionConfiguration defaultConfiguration];  
    [NSURLProtocol unregisterClass:[DMURLProtocol class]];  
    if ([sessionConfiguration isSwizzle]) {  
        // 取消交换  
        [sessionConfiguration unload];  
    }  
}  

到此,基本完成了整个网络流量监控。

再提供一个 Manger 方便使用者调用:

#import <Foundation/Foundation.h>  
  
@class DMNetworkLog;  
@interface DMNetworkTrafficManager : NSObject  
  
/** 所有 NSURLProtocol 对外设置接口,可以防止其他外来监控 NSURLProtocol */  
@property (nonatomic, strong) NSArray *protocolClasses;  
  
  
/** 单例 */  
+ (DMNetworkTrafficManager *)manager;  
  
/** 通过 protocolClasses 启动流量监控模块 */  
+ (void)startWithProtocolClasses:(NSArray *)protocolClasses;  
/** 仅以 DMURLProtocol 启动流量监控模块 */  
+ (void)start;  
/** 停止流量监控 */  
+ (void)end;  
  
@end  

#import "DMNetworkTrafficManager.h"  
#import "DMURLProtocol.h"  
  
@interface DMNetworkTrafficManager ()  
  
@end  
  
@implementation DMNetworkTrafficManager  
  
#pragma mark - Public  
  
+ (DMNetworkTrafficManager *)manager {  
    static DMNetworkTrafficManager *manager;  
    static dispatch_once_t onceToken;  
    dispatch_once(&onceToken, ^{  
        manager=[[DMNetworkTrafficManager alloc] init];  
    });  
    return manager;  
}  
  
+ (void)startWithProtocolClasses:(NSArray *)protocolClasses {  
    [self manager].protocolClasses = protocolClasses;  
    [DMURLProtocol start];  
}  
  
+ (void)start {  
    [self manager].protocolClasses = @[[DMURLProtocol class]];  
    [DMURLProtocol start];  
}  
  
+ (void)end {  
    [DMURLProtocol end];  
}  
  
@end  

五、代码

本文中贴出了比较多的代码,为了便于大家整体观看,可以到 这里[12] 来阅读。

由于其中包含了一些数据操作的内容不需要关心,所以我直接省略了,虽然没有 Demo,但我相信大家都是能理解整个监控结构的。

六、Other

如果你的 APP 从 iOS 9 支持,可以使用 NetworkExtension,通过 NetworkExtension 可以通过 VPN 的形式接管整个网络请求,省掉了上面所有的烦恼。

参考

[1]https://github.com/aozhimin/iOS-Monitor-Platform
[2]https://github.com/zixun/GodEye
[3]https://github.com/zixun/NetworkEye
[4]https://tech.meituan.com/2016/12/19/hertz.html
[5]http://liujinlongxa.com/2016/12/20/使用NSURLProtocol注意的一些问题/
[6]https://github.com/Draveness/analyze/blob/master/contents/OHHTTPStubs/iOS%20开发中使用%20NSURLProtocol%20拦截%20HTTP%20请求.md
[7]https://www.jianshu.com/p/49e7282e888d
[8]https://developer.apple.com/documentation/foundation/nsurlprotocol?language=occ
[9]https://github.com/nicklockwood/GZIP
[10]https://stackoverflow.com/questions/5695914/nsurlrequest-where-an-app-can-find-the-default-headers-for-http-request
[11]https://stackoverflow.com/questions/21694886/nsmutableurlrequest-cant-access-all-request-headers-sent-out-from-within-my-iph
[12]https://github.com/summertian4/iOS-ObjectiveC/tree/master/NetworkTraffic


黑客/网络安全学习路线

对于从来没有接触过黑客/网络安全的同学,目前网络安全、信息安全也是计算机大学生毕业薪资相对较高的学科。

大白也帮大家准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

这也是耗费了大白近四个月的时间,吐血整理,文章非常非常长,觉得有用的话,希望粉丝朋友帮忙点个**「分享」「收藏」「在看」「赞」**

网络安全/渗透测试法律法规必知必会****

今天大白就帮想学黑客/网络安全技术的朋友们入门必须先了解法律法律。

【网络安全零基础入门必知必会】网络安全行业分析报告(01)

【网络安全零基础入门必知必会】什么是黑客、白客、红客、极客、脚本小子?(02)

【网络安全零基础入门必知必会】网络安全市场分类(03)

【网络安全零基础入门必知必会】常见的网站攻击方式(04)

【网络安全零基础入门必知必会】网络安全专业术语全面解析(05)

【网络安全入门必知必会】《中华人民共和国网络安全法》(06)

【网络安全零基础入门必知必会】《计算机信息系统安全保护条例》(07)

【网络安全零基础入门必知必会】《中国计算机信息网络国际联网管理暂行规定》(08)

【网络安全零基础入门必知必会】《计算机信息网络国际互联网安全保护管理办法》(09)

【网络安全零基础入门必知必会】《互联网信息服务管理办法》(10)

【网络安全零基础入门必知必会】《计算机信息系统安全专用产品检测和销售许可证管理办法》(11)

【网络安全零基础入门必知必会】《通信网络安全防护管理办法》(12)

【网络安全零基础入门必知必会】《中华人民共和国国家安全法》(13)

【网络安全零基础入门必知必会】《中华人民共和国数据安全法》(14)

【网络安全零基础入门必知必会】《中华人民共和国个人信息保护法》(15)

【网络安全零基础入门必知必会】《网络产品安全漏洞管理规定》(16)

网络安全/渗透测试linux入门必知必会

【网络安全零基础入门必知必会】什么是Linux?Linux系统的组成与版本?什么是命令(01)

【网络安全零基础入门必知必会】VMware下载安装,使用VMware新建虚拟机,远程管理工具(02)

【网络安全零基础入门必知必会】VMware常用操作指南(非常详细)零基础入门到精通,收藏这一篇就够了(03)

【网络安全零基础入门必知必会】CentOS7安装流程步骤教程(非常详细)零基入门到精通,收藏这一篇就够了(04)

【网络安全零基础入门必知必会】Linux系统目录结构详细介绍(05)

【网络安全零基础入门必知必会】Linux 命令大全(非常详细)零基础入门到精通,收藏这一篇就够了(06)

【网络安全零基础入门必知必会】linux安全加固(非常详细)零基础入门到精通,收藏这一篇就够了(07)

网络安全/渗透测试****计算机网络入门必知必会****

【网络安全零基础入门必知必会】TCP/IP协议深入解析(非常详细)零基础入门到精通,收藏这一篇就够了(01)

【网络安全零基础入门必知必会】什么是HTTP数据包&Http数据包分析(非常详细)零基础入门到精通,收藏这一篇就够了(02)

【网络安全零基础入门必知必会】计算机网络—子网划分、子网掩码和网关(非常详细)零基础入门到精通,收藏这一篇就够了(03)

网络安全/渗透测试入门之HTML入门必知必会

【网络安全零基础入门必知必会】什么是HTML&HTML基本结构&HTML基本使用(非常详细)零基础入门到精通,收藏这一篇就够了1

【网络安全零基础入门必知必会】VScode、PhpStorm的安装使用、Php的环境配置,零基础入门到精通,收藏这一篇就够了2

【网络安全零基础入门必知必会】HTML之编写登录和文件上传(非常详细)零基础入门到精通,收藏这一篇就够了3

网络安全/渗透测试入门之Javascript入门必知必会

【网络安全零基础入门必知必会】Javascript语法基础(非常详细)零基础入门到精通,收藏这一篇就够了(01)

【网络安全零基础入门必知必会】Javascript实现Post请求、Ajax请求、输出数据到页面、实现前进后退、文件上传(02)

网络安全/渗透测试入门之Shell入门必知必会

【网络安全零基础入门必知必会】Shell编程基础入门(非常详细)零基础入门到精通,收藏这一篇就够了(第七章)

网络安全/渗透测试入门之PHP入门必知必会

【网络安全零基础入门】PHP环境搭建、安装Apache、安装与配置MySQL(非常详细)零基础入门到精通,收藏这一篇就够(01)

【网络安全零基础入门】PHP基础语法(非常详细)零基础入门到精通,收藏这一篇就够了(02)

【网络安全零基础入门必知必会】PHP+Bootstrap实现表单校验功能、PHP+MYSQL实现简单的用户注册登录功能(03)

网络安全/渗透测试入门之MySQL入门必知必会

【网络安全零基础入门必知必会】MySQL数据库基础知识/安装(非常详细)零基础入门到精通,收藏这一篇就够了(01)

【网络安全零基础入门必知必会】SQL语言入门(非常详细)零基础入门到精通,收藏这一篇就够了(02)

【网络安全零基础入门必知必会】MySQL函数使用大全(非常详细)零基础入门到精通,收藏这一篇就够了(03)

【网络安全零基础入门必知必会】MySQL多表查询语法(非常详细)零基础入门到精通,收藏这一篇就够了(04)

****网络安全/渗透测试入门之Python入门必知必会

【网络安全零基础入门必知必会】之Python+Pycharm安装保姆级教程,Python环境配置使用指南,收藏这一篇就够了【1】

【网络安全零基础入门必知必会】之Python编程入门教程(非常详细)零基础入门到精通,收藏这一篇就够了(2)

python开发之手写第一个python程序

python开发笔记之变量

python基础语法特征

python开发数据类型

python开发笔记之程序交互

python入门教程之python开发学习笔记基本数据类型

python入门教程之python开发笔记之格式化输出

python入门教程之python开发笔记基本运算符

python入门教程python开发基本流程控制if … else

python入门教程之python开发笔记流程控制之循环

python入门之Pycharm开发工具的使用

python入门教程之python字符编码转换

python入门之python开发字符编码

python入门之python开发基本数据类型数字

python入门python开发基本数据类型字符串

python入门python开发基本数据类型列表

python入门python开发基本数据类型

python入门教程之python开发可变和不可变数据类型和hash

python入门教程python开发字典数据类型

python入门之python开发笔记基本数据类型集合

python开发之collections模块

python开发笔记之三元运算

【网络安全零基础入门必知必会】之10个python爬虫入门实例(非常详细)零基础入门到精通,收藏这一篇就够了(3)

****网络安全/渗透测试入门之SQL注入入门必知必会

【网络安全渗透测试零基础入门必知必会】之初识SQL注入(非常详细)零基础入门到精通,收藏这一篇就够了(1)

【网络安全渗透测试零基础入门必知必会】之SQL手工注入基础语法&工具介绍(2)

【网络安全渗透测试零基础入门必知必会】之SQL注入实战(非常详细)零基础入门到精通,收藏这一篇就够了(3)

【网络安全渗透测试零基础入门必知必会】之SQLmap安装&实战(非常详细)零基础入门到精通,收藏这一篇就够了(4)

【网络安全渗透测试零基础入门必知必会】之SQL防御(非常详细)零基础入门到精通,收藏这一篇就够了(4)

****网络安全/渗透测试入门之XSS攻击入门必知必会

【网络安全渗透测试零基础入门必知必会】之XSS攻击基本概念和原理介绍(非常详细)零基础入门到精通,收藏这一篇就够了(1)

网络安全渗透测试零基础入门必知必会】之XSS攻击获取用户cookie和用户密码(实战演示)零基础入门到精通收藏这一篇就够了(2)

【网络安全渗透测试零基础入门必知必会】之XSS攻击获取键盘记录(实战演示)零基础入门到精通收藏这一篇就够了(3)

【网络安全渗透测试零基础入门必知必会】之xss-platform平台的入门搭建(非常详细)零基础入门到精通,收藏这一篇就够了4

【网络安全渗透测试入门】之XSS漏洞检测、利用和防御机制XSS游戏(非常详细)零基础入门到精通,收藏这一篇就够了5

****网络安全/渗透测试入门文件上传攻击与防御入门必知必会

【网络安全渗透测试零基础入门必知必会】之什么是文件包含漏洞&分类(非常详细)零基础入门到精通,收藏这一篇就够了1

【网络安全渗透测试零基础入门必知必会】之cve实际漏洞案例解析(非常详细)零基础入门到精通, 收藏这一篇就够了2

【网络安全渗透测试零基础入门必知必会】之PHP伪协议精讲(文件包含漏洞)零基础入门到精通,收藏这一篇就够了3

【网络安全渗透测试零基础入门必知必会】之如何搭建 DVWA 靶场保姆级教程(非常详细)零基础入门到精通,收藏这一篇就够了4

【网络安全渗透测试零基础入门必知必会】之Web漏洞-文件包含漏洞超详细全解(附实例)5

【网络安全渗透测试零基础入门必知必会】之文件上传漏洞修复方案6

****网络安全/渗透测试入门CSRF渗透与防御必知必会

【网络安全渗透测试零基础入门必知必会】之CSRF漏洞概述和原理(非常详细)零基础入门到精通, 收藏这一篇就够了1

【网络安全渗透测试零基础入门必知必会】之CSRF攻击的危害&分类(非常详细)零基础入门到精通, 收藏这一篇就够了2

【网络安全渗透测试零基础入门必知必会】之XSS与CSRF的区别(非常详细)零基础入门到精通, 收藏这一篇就够了3

【网络安全渗透测试零基础入门必知必会】之CSRF漏洞挖掘与自动化工具(非常详细)零基础入门到精通,收藏这一篇就够了4

【网络安全渗透测试零基础入门必知必会】之CSRF请求伪造&Referer同源&置空&配合XSS&Token值校验&复用删除5

****网络安全/渗透测试入门SSRF渗透与防御必知必会

【网络安全渗透测试零基础入门必知必会】之SSRF漏洞概述及原理(非常详细)零基础入门到精通,收藏这一篇就够了 1

【网络安全渗透测试零基础入门必知必会】之SSRF相关函数和协议(非常详细)零基础入门到精通,收藏这一篇就够了2

【网络安全渗透测试零基础入门必知必会】之SSRF漏洞原理攻击与防御(非常详细)零基础入门到精通,收藏这一篇就够了3**
**

****网络安全/渗透测试入门XXE渗透与防御必知必会

【网络安全渗透测试零基础入门必知必会】之XML外部实体注入(非常详细)零基础入门到精通,收藏这一篇就够了1

网络安全渗透测试零基础入门必知必会】之XXE的攻击与危害(非常详细)零基础入门到精通,收藏这一篇就够了2

【网络安全渗透测试零基础入门必知必会】之XXE漏洞漏洞及利用方法解析(非常详细)零基础入门到精通,收藏这一篇就够了3

【网络安全渗透测试零基础入门必知必会】之微信XXE安全漏洞处理(非常详细)零基础入门到精通,收藏这一篇就够了4

****网络安全/渗透测试入门远程代码执行渗透与防御必知必会

【网络安全渗透测试零基础入门必知必会】之远程代码执行原理介绍(非常详细)零基础入门到精通,收藏这一篇就够了1

【网络安全零基础入门必知必会】之CVE-2021-4034漏洞原理解析(非常详细)零基础入门到精通,收藏这一篇就够了2

【网络安全零基础入门必知必会】之PHP远程命令执行与代码执行原理利用与常见绕过总结3

【网络安全零基础入门必知必会】之WEB安全渗透测试-pikachu&DVWA靶场搭建教程,零基础入门到精通,收藏这一篇就够了4

****网络安全/渗透测试入门反序列化渗透与防御必知必会

【网络安全零基础入门必知必会】之什么是PHP对象反序列化操作(非常详细)零基础入门到精通,收藏这一篇就够了1

【网络安全零基础渗透测试入门必知必会】之php反序列化漏洞原理解析、如何防御此漏洞?如何利用此漏洞?2

【网络安全渗透测试零基础入门必知必会】之Java 反序列化漏洞(非常详细)零基础入门到精通,收藏这一篇就够了3

【网络安全渗透测试零基础入门必知必会】之Java反序列化漏洞及实例解析(非常详细)零基础入门到精通,收藏这一篇就够了4

【网络安全渗透测试零基础入门必知必会】之CTF题目解析Java代码审计中的反序列化漏洞,以及其他漏洞的组合利用5

网络安全/渗透测试**入门逻辑漏洞必知必会**

【网络安全渗透测试零基础入门必知必会】之一文带你0基础挖到逻辑漏洞(非常详细)零基础入门到精通,收藏这一篇就够了

网络安全/渗透测试入门暴力猜解与防御必知必会

【网络安全渗透测试零基础入门必知必会】之密码安全概述(非常详细)零基础入门到精通,收藏这一篇就够了1

【网络安全渗透测试零基础入门必知必会】之什么样的密码是不安全的?(非常详细)零基础入门到精通,收藏这一篇就够了2

【网络安全渗透测试零基础入门必知必会】之密码猜解思路(非常详细)零基础入门到精通,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之利用Python暴力破解邻居家WiFi密码、压缩包密码,收藏这一篇就够了4

【网络安全渗透测试零基础入门必知必会】之BurpSuite密码爆破实例演示,零基础入门到精通,收藏这一篇就够了5

【网络安全渗透测试零基础入门必知必会】之Hydra密码爆破工具使用教程图文教程,零基础入门到精通,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之暴力破解medusa,零基础入门到精通,收藏这一篇就够了7

【网络安全渗透测试零基础入门必知必会】之Metasploit抓取密码,零基础入门到精通,收藏这一篇就够了8

Wfuzz:功能强大的web漏洞挖掘工具

****网络安全/渗透测试入门掌握Redis未授权访问漏洞必知必会

【网络安全渗透测试零基础入门必知必会】之Redis未授权访问漏洞,零基础入门到精通,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之Redis服务器被攻击后该如何安全加固,零基础入门到精通,收藏这一篇就够了**
**

网络安全/渗透测试入门掌握**ARP渗透与防御关必知必会**

【网络安全渗透测试零基础入门必知必会】之ARP攻击原理解析,零基础入门到精通,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之ARP流量分析,零基础入门到精通,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之ARP防御策略与实践指南,零基础入门到精通,收藏这一篇就够了

网络安全/渗透测试入门掌握系统权限提升渗透与防御关****必知必会

【网络安全渗透测试零基础入门必知必会】之Windows提权常用命令,零基础入门到精通,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之Windows权限提升实战,零基础入门到精通,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之linux 提权(非常详细)零基础入门到精通,收藏这一篇就够了

网络安全/渗透测试入门掌握Dos与DDos渗透与防御相关****必知必会

【网络安全渗透测试零基础入门必知必会】之DoS与DDoS攻击原理(非常详细)零基础入门到精通,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之Syn-Flood攻击原理解析(非常详细)零基础入门到精通,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之IP源地址欺骗与dos攻击,零基础入门到精通,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之SNMP放大攻击原理及实战演示,零基础入门到精通,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之NTP放大攻击原理,零基础入门到精通,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之什么是CC攻击?CC攻击怎么防御?,零基础入门到精通,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之如何防御DDOS的攻击?零基础入门到精通,收藏这一篇就够了

网络安全/渗透测试入门掌握无线网络安全渗透与防御相关****必知必会

【网络安全渗透测试零基础入门必知必会】之Aircrack-ng详细使用安装教程,零基础入门到精通,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之aircrack-ng破解wifi密码(非常详细)零基础入门到精通,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之WEB渗透近源攻击,零基础入门到精通,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之无线渗透|Wi-Fi渗透思路,零基础入门到精通,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之渗透WEP新思路Hirte原理解析,零基础入门到精通,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之WPS的漏洞原理解析,零基础入门到精通,收藏这一篇就够了

网络安全/渗透测试入门掌握木马免杀问题与防御********必知必会

【网络安全渗透测试零基础入门必知必会】之Metasploit – 木马生成原理和方法,零基础入门到精通,收藏这篇就够了

【网络安全渗透测试零基础入门必知必会】之MSF使用教程永恒之蓝漏洞扫描与利用,收藏这一篇就够了

网络安全/渗透测试入门掌握Vulnhub靶场实战********必知必会

【网络安全渗透测试零基础入门必知必会】之Vulnhub靶机Prime使用指南,零基础入门到精通,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之Vulnhub靶场Breach1.0解析,零基础入门到精通,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之vulnhub靶场之DC-9,零基础入门到精通,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之Vulnhub靶机Kioptrix level-4 多种姿势渗透详解,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之Vulnhub靶场PWNOS: 2.0 多种渗透方法,收藏这一篇就够了

网络安全/渗透测试入门掌握社会工程学必知必会

【网络安全渗透测试零基础入门必知必会】之什么是社会工程学?定义、类型、攻击技术,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之社会工程学之香农-韦弗模式,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之社工学smcr通信模型,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之社会工程学之社工步骤整理(附相应工具下载)收藏这一篇就够了

网络安全/渗透测试入门掌握********渗透测试工具使用******必知必会**

2024版最新Kali Linux操作系统安装使用教程(非常详细)零基础入门到精通,收藏这一篇就够了

【网络安全渗透测试零基础入门必知必会】之渗透测试工具大全之Nmap安装使用命令指南,零基础入门到精通,收藏这一篇就够了

2024版最新AWVS安装使用教程(非常详细)零基础入门到精通,收藏这一篇就够了

2024版最新burpsuite安装使用教程(非常详细)零基础入门到精通,收藏这一篇就够了

2024版最新owasp_zap安装使用教程(非常详细)零基础入门到精通,收藏这一篇就够了

2024版最新Sqlmap安装使用教程(非常详细)零基础入门到精通,收藏这一篇就够了

2024版最新Metasploit安装使用教程(非常详细)零基础入门到精通,收藏这一篇就够了

2024版最新Nessus下载安装激活使用教程(非常详细)零基础入门到精通,收藏这一篇就够了

2024版最新Wireshark安装使用教程(非常详细)零基础入门到精通,收藏这一篇就够了

觉得有用的话,希望粉丝朋友帮大白点个**「分享」「收藏」「在看」「赞」**

黑客/网络安全学习包

资料目录

  1. 成长路线图&学习规划

  2. 配套视频教程

  3. SRC&黑客文籍

  4. 护网行动资料

  5. 黑客必读书单

  6. 面试题合集

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

1.成长路线图&学习规划

要学习一门新的技术,作为新手一定要先学习成长路线图,方向不对,努力白费。

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图&学习规划。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。


因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

2.视频教程

很多朋友都不喜欢晦涩的文字,我也为大家准备了视频教程,其中一共有21个章节,每个章节都是当前板块的精华浓缩。


因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

3.SRC&黑客文籍

大家最喜欢也是最关心的SRC技术文籍&黑客技术也有收录

SRC技术文籍:

黑客资料由于是敏感资源,这里不能直接展示哦!

4.护网行动资料

其中关于HW护网行动,也准备了对应的资料,这些内容可相当于比赛的金手指!

5.黑客必读书单

**

**

6.面试题合集

当你自学到这里,你就要开始思考找工作的事情了,而工作绕不开的就是真题和面试题。

更多内容为防止和谐,可以扫描获取~

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

cookie提取:登录后提取在线cookie,更新至服务器或副本至剪切板,为爬虫抓取跳过复杂验证码识别程序 Cookies提取助手(cookie提取) 入门爬虫,基本上都会遇到的交换---“验证码”(阻止程序自动化)。就是这个东西有着很多程序的自动化工作止步,让人懊恼不已。 Cookies提取助手的出现,可以通过手工输入验证码,免去程序实现验证码识别的繁琐实现,提取有效可用的Cookie,提供给爬虫抓取程序,实现免验证码爬取。 功能特点 自定义服务器地址(API) 操作简单,页面快捷菜单提取 可将Cookies上传至服务器,长期使用 可将Cookies复制至剪切板,调试快捷使用 注意事项 适用场景:验证码登录才能爬取的网站,手动输入验证码获取有效的Cookie使用,并且网站未针对Cookie进行反爬虫处理。 安装 chrome浏览器,设置->更多工具->扩展程序 开拓开发者模式 拖拽* .crx包至此扩展页面释放,确认安装即可 详细操作步骤,参考: : 使用 点击浏览器“ Cookies提取助手”扩展程序按钮,弹框里输入HTTP服务器接口地址 登录需要爬取的网站成功后,在页面点击鼠标右键 选择“ Cookies提取助手” 选择“提取Cookie更新服务器” 选择“提取Cookies至剪 立即下载

相关推荐

网络流量监视软件-查看网络状态如TCP/IP状态,UDP和ICMP状态等信息

是一个专用的软件流量监视软件,可以显示总发送接收速率,同时也估计当前的传输速度,不管是针对ADSL或者MODEN的用户都非常有用,并且软件界面可以更换字体,软件可以详细查看网络状态如TCP/IP状态,UDP和ICMP状态等信息,同时软件支持透明窗体.

小白联通300M流量领取工具

介绍: 小白联通300M流量领取工具 网盘下载地址: https://zijiewangpan.com/xRs7DIbu6ZA 图片:

php源码 237

流量监控精灵 流量监控精灵 v1.0

流量监控精灵是一款轻巧的系统流量监控软件,可以实时获取网卡的上传和下载数据大小,并进行一个总流量的核算,帮助用户了解宽带的使用情况,除此之外,还加上了CPU和RAM内存信

【超详细】服务器使用青龙面板跑联通余量脚本并接收钉钉机器人定时推送超详细教程

【超详细】服务器使用青龙面板跑联通余量脚本并接收钉钉机器人定时推送超详细教程

qq_32448877的博客 9219

【GAMES101】现代计算机图形学入门 资料整理

课程网址 课程主页 包括ppt 课程PPT和视频 一篇搞定!GAMES101现代计算机图形学入门(全) 作业链接地址 作业论坛 GAMES101课程环境搭建(Win10+VSCode) 计算机图形学笔记 虎书pdf 提取:n2rx 【必须】:高等数学(微积分、线性代数)、算法、数据结构 【非必须】:信号处理、数值分析、大学物理(光学) 在线公式编辑器 一定要做作业,如果个人要配置环境的话应该是配置opencv,eigen这两个核心库就行了,目前觉得最核心的一个作业是作业3,实现着色器和渲染管线,做完一遍

ysh的博客 2684

C#与西门子PLC通讯——新手快速入门

本文基于C# .Net Core和西门子博图TIA Portal V17搭建。由于手边没有西门子PLC实物,所以采用S7-PLCSIM Advanced V4.0作为模拟PLC,以实现0成本完成通讯测试实例。这篇入门笔记解决了新手第一次上手实践时遇到的坑,并且有意忽略了实际项目中会遇到的逻辑交互和更多的数据格式问题。

吾家有猫名探花的博客 2万+

联通流量监控项目教程

联通流量监控项目教程 1、项目介绍 联通流量监控是一个开源项目,旨在帮助用户监控和管理联通网络的流量使用情况。该项目由JunXiaoRuo开发,基于GPL-3.0许可证发布。用户可以通过该项目实时监控流量使用情况,并进行相应的管理和优化。 2、项目快速启动 环境准备 在开始之前,请确保您的开发环境已经安装了以下工具: Java开发工具包(JDK) Gradle构建工具 Git版本控制工具 克隆...

gitblog_00073的博客 726

【本体】Protege高效批量导入实例(Individuals)的自动化实践

本文详细介绍了在Protege中高效批量导入实例(Individuals)的自动化实践方法。通过分析Protege本体文件结构,提供Python脚本示例,帮助用户快速处理大规模数据导入,显著提升知识图谱构建效率。特别适合需要处理数千个实例的医疗、制药等领域应用。

weixin_30275415的博客 408

【亲测免费】 联通余量:一款高效便捷的流量监控工具

联通余量:一款高效便捷的流量监控工具 项目介绍 联通余量是一款专为中国联通用户设计的流量监控工具,旨在帮助用户实时掌握自己的流量使用情况。通过该工具,用户可以轻松查看当前的流量余量、套餐详情以及历史使用记录,从而更好地管理自己的移动数据。 项目技术分析 联通余量项目采用了现代化的技术栈,确保了工具的高效性和稳定性。以下是项目的主要技术特点: 前端技术:项目前端采用了React框架,结合TypeS...

gitblog_00374的博客 1736

Creo报错代码-9?手把手教你重新生成许可证文件(基于Creo 10.0)

本文详细解析Creo报错代码-9的成因及解决方案,重点介绍如何重新生成许可证文件以应对网络环境变化导致的验证失败。通过分步指南和高级技巧,帮助用户有效管理多网络环境下的Creo许可证问题,提升工作效率。

weixin_30839881的博客 560

上、下拉电阻(定义、强弱上拉、常见作用、吸电流、拉电流、灌电流)

1.上、下拉电阻定义 上拉电阻是把一个信号通过一个电阻接到电源(Vcc),下拉电阻是一个信号通过一个电阻接到地(GND)。 2.强上拉、弱上拉 强上拉、弱上拉的强弱只是上拉电阻的阻值不同,没有什么严格区分。例如:50Ω上拉,一般成为强上拉;100kΩ上拉则称为弱上拉。下拉也是一样的。强拉电阻的极端就是0Ω电阻,即将信号线直接与电源或低相连接。 3.上、下拉电阻的作用 因为上下拉电阻的作用概念很宽泛,不用领域的使用方法也不同,常见使用方法整理如下: ...

小浪宝宝的博客 3万+

iOS 流量监控分析

黑客技术点击右侧关注,了解黑客的世界!Java开发进阶点击右侧关注,掌握进阶之路!Linux编程点击右侧关注,免费入门到精通!作者 | 小鱼周凌宇,目前在饿了么物流iOS...

iOS_开发 1714

泛微OA E9文档管理优化:临时文件清理与存储配置指南

本文深入解析了泛微OA E9系统性能下降的常见原因——临时文件堆积,并提供了完整的优化配置指南。文章详细介绍了临时文件的产生机制,并手把手指导管理员如何通过修改存储路径、调整保留时间、设置白名单等关键配置,有效清理与管理系统临时文件,从而释放存储空间,提升系统运行效率与稳定性。

tree8的博客 431

app测试指南,零基础入门到精通,收藏这篇就够了

*工具实战:**集中训练抓包工具(Wireshark)、渗透测试工具(Nmap)、漏洞扫描工具(Nessus 基础版)的使用,结合模拟场景练习工具应用(掌握基础扫描逻辑,为 SRC 漏扫工具进阶做准备)。实战技能训练:开展漏洞扫描、漏洞利用、电商系统渗透测试、内网渗透、权限提升(Windows、Linux)、代码审计等实战训练,结合运维中熟悉的系统环境设计测试场景(强化红蓝对抗攻击端技术能力)。红蓝对抗基础:学习护网行动背景、红蓝对抗规则(攻击范围、禁止行为)、红蓝双方角色职责(红队:模拟攻击;

Libra1313的博客 906

YOLOv11涨点改进 | 全网独家创新,损失函数改进篇 | TGRS 2025 | 引入AdaFocalLoss损失函数,改进小目标检测,自适应聚焦小目标与样本分布不平衡,提升检测精度与训练稳定性

本文提出了一种改进YOLOv11模型的AdaFocalLoss损失函数,通过动态调节机制有效提升小目标检测性能。AdaFocalLoss融合了目标尺寸感知和IoU引导的自适应调节,解决了传统损失函数在小目标检测中的样本不平衡问题。该方法自动调整训练权重,无需手动调参,显著提升了模型在多尺度目标、复杂背景下的检测精度和训练稳定性。实验表明,AdaFocalLoss能更好地平衡不同尺度目标的梯度分布,改善边界完整性,减少误检漏检。文章详细介绍了算法原理、实现代码和在YOLOv11中的集成方法,为提升目标检测性能

Ai缝合怪、助力小伙伴高效发论文 336

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

网络运维需要学什么(非常详细)零基础入门到精通,收藏这篇就够了

运维工程师需要掌握的网络技能涵盖了从基础到高级的多个方面。通过不断学习和实践,掌握这些网络技能,运维工程师将能够更好地应对各种网络环境和问题,确保系统的稳定运行。技术是基础,态度是关键,坚持不懈地学习和提升,你一定能在运维工程师的道路上越走越远,为企业的发展贡献更大的力量。35岁+运维人员的发展与出路经常有人问我:干网工、干运维多年遇瓶颈,想学点新技术给自己涨涨“身价”,应该怎么选择?聪明人早已经用脚投票:近年来,越来越多运维的朋友寻找新的职业发展机会,将目光聚焦到了网络安全产业。

Javachichi的博客 3366

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

网络运维软件大全,零基础入门到精通,收藏这篇就够了

网络运维工程师作为企业信息安全的守护者,他们的工作不仅仅是修复硬件问题,更多的是确保企业的网络环境稳定、数据安全。为了完成这一目标,他们需要掌握各种软件工具。本文将为您介绍网络运维工程师必备的软件工具,帮助您更好地了解这个行业。Wireshark是一款开源的网络协议分析器,它可以帮助网络运维工程师捕获和分析网络数据包。通过使用Wireshark,您可以深入了解网络流量、识别异常行为、定位故障原因等。

A1_3_9_7的博客 948

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

渗透测试的8个步骤(超详细),小白必看!(非常详细)从零基础到精通,收藏这篇就够了

渗透测试的8个步骤(超详细)

weixin_57514792的博客 3247

网工模拟软件大全,零基础入门到精通,收藏这篇就够了

Wireshark,这玩意儿是我网络生涯的“老战友”,开源免费,跨平台(Win/Mac/Linux),专治各种不明流量。界面直观,左侧包列表,中间十六进制,右侧树状协议细节,过滤器神了,比如“ip.src 192.168.1.100 and tcp.port 80”直击痛点。**工具实战:**集中训练抓包工具(Wireshark)、渗透测试工具(Nmap)、漏洞扫描工具(Nessus 基础版)的使用,结合模拟场景练习工具应用(掌握基础扫描逻辑,为 SRC 漏扫工具进阶做准备)。

Libra1313的博客 1148

App专项测试测试有哪些?零基础入门到精通,收藏这篇就够了

针对App通常会考虑这些方面:1 操作系统版本2 屏幕分辨率3 不同厂家的ROM4) 网络类型比如Wifi、3G、4G、5G下的功能情况在 移动产品的测试中,很有必要对App使用的流量进行度量,大致来说,流量可以从用户使用的的相关性角度分为:一类是用户的操作直接导致的流量消耗;另一类是后台,即在用户没有直接使用情况下的流量消耗。在木器电池 技术没有取得巨大突破前提下,这方面始终会存在一些瓶颈,如果一些App架构设计的不好,或者代码偶缺陷,就可能导致电量消耗比较高,所以电量测试也是很重要的。

leah126的博客 387

护网行动是什么?如何成为HW中的蓝队和红队?零基础到实战精通,看这一篇就够了!

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取。

weixin_57514792的博客 955
上一篇: 详解网络流量监控​,从零基础到精通,收藏这篇就够了!
下一篇: 【2025版】值得入坑AI Agent的五大框架,从零基础到精通,精通收藏这篇就够了!
程序员_大白
博客等级 码龄5年 1万+粉丝 4001原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值