大部分的iOS开发在刚开始接触网络请求时,应该都是用的AFNetworking这个在iOS界扛把子的框架来做的吧,但你们知道这个框架在做网络请求的时候都做了什么吗。这篇文章会从系统原生的网络请求来揭示网络请求的本质,以后如果有时间会简单解析AFNetworking的源码。
原生网络请求分为三个部分:
- NSMutableURLRequest请求类
先来一张网络请求的抓包信息图:
网络请求抓包.png
图片来自:编程小翁
上图便是一个完整的网络请求的抓包示意图,NSMutableURLRequest这个类就是管理者上半部分的所有信息,如下图框出来的部分:
网络请求抓包.png
图片来自:编程小翁
其实就是网络请求中的HTTPHeaderField信息。我们来一一细说其中作用(其中着重看Content-Type、Cookie、Content-Length,因为我们配置这些就行了。另外还有一个重要字段图中没有,那就是传输的内容HTTPBody
代码中会讲到)。
POST:这个可以是GET或者别的请求方式,这里放的是URL后半段
Host:这里是主机地址,Host和POST字段拼接起来就是一个完整的URL
Accept:这个网络请求发送的数据的格式说明:如Accept:text/html,这说明这个网络请求发送的
是HTML格式的数据。图中的Accept:*/* 为通用格式。
Content-Type:这个字段表明数据发送方(也就是我们客户端)想要接收的数据格式,一下有一个格式
对照表的截图。
Connection:网络请求连接的方式,这个我们不用设置。
Cookie:我们只能从服务器得到这个字段,用于维持服务端会话状态,也可以用来做接口验证,类似
token这样的。并且在iOS中,如果请求中cookie字段有值,苹果会自动帮我们保存下来,
代码中会讲。
Accept-Language:表明可以接收什么文字,zh-cn表示中文。
Content-Length:表示传输内容的长度。
Accept-Encoding:表示客户端支持的编码格式,这个不用我们配置。
User-Agent:这个就像是一个网名,随便写都可以,一般不做配置。
创建一个NSMutableURLRequest
/** 创建request对象 */
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
/** 这个操作就是检测cookie的方法,我们的系统会自动将cookie保存下来,通过下面的方法可以检测出来,如果服务器要求我们同步cookie,则在request中设置Cookie的值 */
NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in [cookieJar cookies]) {
if (cookie != nil) {
NSDictionary *headers=[NSHTTPCookie requestHeaderFieldsWithCookies:[cookieJar cookies]];
[request setValue:[headers objectForKey:@"Cookie"] forHTTPHeaderField:@"Cookie"];
}
}
/**
如果传入参数不为空,则为POST请求
如果传入的参数为nil,则为GET请求
*/
if (parameters != nil && parameters.count > 0) {
/** 传入的参数为一个字典,我们需要把字典转化为一个以"&"分隔的字符串,再将字符串转化为data,最后设置到HTTPBody里面去 */
NSData *bodyData = [self getDataFromParameters:parameters];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:bodyData];
[request setValue:[NSString stringWithFormat:@"%lld",(long long)bodyData.length] forHTTPHeaderField:@"Content-Length"];
/** 这个可以固定 */
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
}
/** 设置请求时间 */
request.timeoutInterval = 8.0;
- NSURLSession会话类
- NSURLSessionDataTask会话任务类
把这两个放到一起讲,是因为这两个很简单。一个request请求需要一个会话来启动和管理,但我们仅仅只需要一个创建一个对象就行了
/** 创建会话对象 */
NSURLSession *session = [NSURLSession sharedSession];
最后我们需要把会话对象用来创建一个任务对象就完成了:
/** 创建会话任务,并用会话对象启动请求对象 */
NSURLSessionDataTask *sessionDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
}];
注意一点:会话任务需要手动启动
/** 开始任务 */
[sessionDataTask resume];
至此,系统原生的网络请求就完成了。
demo地址