HTTPS
流程图
流程
- HTTPS = http + ssl/tls
TCP VS UDP
- https://www.cnblogs.com/liangyc/p/11628208.html
区别
- 面向链接VS无链接
- TCP建立一个连接需要3次握手IP数据包,断开连接需要4次握手。另外断开连接时发起方可能进入TIME_WAIT状态长达数分钟(视系统设置,windows一般为120s),在此状态下连接(端口)无法被释放
- UDP不需要建立连接,可以直接发送
- 可靠VS不可靠
- TCP利用握手、ACK和重传机制保证可靠性,UDP则没有
- 校验和、确认应答与序列号、超时重传、连接管理、浏览控制、阻塞控制
- TCP利用握手、ACK和重传机制保证可靠性,UDP则没有
- 有序性
- TCP利用seq序列号对包进行排序,udp没有
- 面向字节流VS面向报文
- 面向报文
- 面向报文的传输方式是应用层交给UDP多长的报文,DUP就照样发送,即一次发送一个报文。因此,应用程序必须选择比较合适大小的报文。若报文太长,则IP层需要分片。UDP对应用层交下来的报文,既不合并、也不拆分,而是保留这些报文的边界。(一个UDP的最大报文长度2^16-1-20-8,20是ip报文头,8是udp报文头)
- 面向字节流
- 面向字节流的话,虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序看成是一连串的无结构的字节流。TCP有一个缓冲,当应用程序传输的数据块太长,TCP就可以把它划分短一些再传送。如果应用程序一次只发送一个字节,TCP也可以等待积累有足够多的字节后再构建成报文段发送出去。
- 面向报文
- TCP有浏览控制,UDP没有
- TCP头部20~60字节,UDP8字节
- 应用场景
- 面向链接VS无链接
TCP -> 传输控制协议,这是传输层的一个协议,对数据的传输进行详细的控制。
- 面向字节流
- 安全可靠
- 面向连接
- TCP可靠性
- 校验和
- 确认应答与序列号
- 超时重传
- 链接管理
- 流量控制
- 阻塞控制
三次握手、四次挥手※
- 为什么不能两次握手?
- 四次挥手时,FIN与ACK分开?
- https://blog.csdn.net/liuchenxia8/article/details/80336292?spm=1001.2014.3001.5501
- 在客户端最后一次发送ACK响应后,进入TIME_WAIT状态,而这个状态的时候客户端在做什么呢?2MSL
- 但是为什么这里服务器发送的FIN与ACK是分开的发送的呢?
UDP
特点
- 无连接
- 不可靠
- 面向数据包
- 速度快
HTTP报文格式
状态码
- 200 -> 成功
- 301 -> 重定向, 302 -> 永久重定向
- 4开头,代表客户端问题,404 -> 资源找不到
-
http1.0、2.0区别
- http2采用二进制格式而不是文本格式
- http2多路复用格式,而非有序并阻塞,只有一个链接即可
- 使用报头压缩,降低了开销
-
用户态 VS 内核态
内核态 -> 控制计算机的资源,如协调CPU资源,分配内存资源,并且提供稳定的运行环境供应用程序运行。
- 用户态 -> 提供应用程序运行的空间,为了使应用程序能访问到的内核管理的资源例如CPU、内存、I/O。内核必须提供一系列通用的访问接口,这些接口就叫操作系统。
- 用户态到内核态切换的三种方式:
- 系统调用 -> 其实系统调用本身就是中断,但是软件中断,跟硬中断不同。
- 异常 -> 如果当前进程运行在用户态,如果这个时候发生了异常事件,就会触发切换。例如:缺页异常。
- 外设中断 -> 当外设完成用户的请求时,会向CPU发送中断信号。
- 中断具体操作步骤
① 从当前进程的描述符中提取其内核栈的ss0及esp0信息。
②使用ss0和esp0指向的内核栈将当前进程的cs,eip,eflags,ss,esp信息保存起来,这个过程也完成了由用户栈到内核栈的切换过程,同时保存了被暂停执行的程序的下一条指令。
③ 将先前由中断向量检索得到的中断处理程序的cs,eip信息装入相应的寄存器,开始执行中断处理程序,这时就转到了内核态的程序执行了。
Socket
- Socket就是插座,端口就是插座上的孔, 端口不能被其他进程占用;
- 抽象理解Socket类似于操作某个IP地址上的某个端口达到点对点通信的目的,
- 绑定到某个具体的进程中和端口中;
服务端:
protobuf序列化为二进制和json序列化字符串大小
- pb:58字节
- json:110字节,删掉空格还有100字节
- 更容容易绑定值到对象的字段上。JSON 的字段是用字符串指定的,相比之下字符串比对应该比基于数字的字段tag更耗时。
- JSON 是文本的格式,整数和浮点数应该更占空间而且更费时。
Protobuf 在正文前有一个大小或者长度的标记,而 JSON 必须全文扫描无法跳过不需要的字段。
Unicode与UTF-8区别
https://www.zhihu.com/question/23374078
进程IPC通信
消息传递(管道、FIFO、消息队列)
- 同步(互斥量、条件变量、读写锁、信号量)
- 共享内存(匿名和具名的)
-
HPACK算法
HTTP2相对HTTP1进行了头部压缩,主要由两张表组成,静态表和动态表
移动端网络优化
一、分析网络请求流程及耗时
(1)网络请求过程
发起请求->域名解析->tcp三次握手->tls握手->request->response->json解析->业务
(2)耗时统计
在了解了网络请求的流程之后,我们可以先测试以下自己项目网络请求耗时分布,对iOS来说。
- 获取耗时最简单的方式就是监听NSURLSession的didFinishCollectingMetrics回调方法
```objectivec
- (void)URLSession:(NSURLSession )session task:(NSURLSessionTask )task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0))
{ if (@available(iOS 10.0, )) { for (NSURLSessionTaskTransactionMetrics sessionMetric in metrics.transactionMetrics) { NSInteger dom = ([sessionMetric.domainLookupEndDate timeIntervalSince1970] - [sessionMetric.domainLookupStartDate timeIntervalSince1970]) 1000 ; NSInteger sec = ([sessionMetric.secureConnectionEndDate timeIntervalSince1970] - [sessionMetric.secureConnectionStartDate timeIntervalSince1970]) 1000; NSInteger con = ([sessionMetric.connectEndDate timeIntervalSince1970] - [sessionMetric.connectStartDate timeIntervalSince1970]) 1000; NSInteger req = ([sessionMetric.requestEndDate timeIntervalSince1970] - [sessionMetric.requestStartDate timeIntervalSince1970]) 1000; NSInteger res = ([sessionMetric.responseEndDate timeIntervalSince1970] - [sessionMetric.responseStartDate timeIntervalSince1970]) 1000; NSInteger tot = ([sessionMetric.responseEndDate timeIntervalSince1970] - [sessionMetric.fetchStartDate timeIntervalSince1970]) 1000;
NSString *locip = @"";
NSString *remip = @"";
if (@available(iOS 13.0, *)) {
locip = [NSString stringWithFormat:@"%@", sessionMetric.localAddress];
remip = [NSString stringWithFormat:@"%@", sessionMetric.remoteAddress];
}
NSLog(@"metric path:%@ 总耗时:%ldms, 域名解析:%ldms, 连接耗时:%ldms(包括TLS:%ldms), 请求:%ldms, 回调:%ldms l:%@ r:%@",sessionMetric.request.URL.lastPathComponent,tot,dom,con,sec,req,res, locip, remip);
}
}
二、优化思路
(1)域名解析耗时
我们常用的HTTP请求,底层基于TCP连接,需要有IP和端口信息。由于IP是可变的,且不好记忆,所以有了域名这样一个字符串帮助人们进行记忆。
字符串到IP需要经过DNS服务器来进行获取,这一过程使用的UDP方式,这一过程的快慢取决于网络质量以及域名映射关系存放的DNS服务器跟你所在地跨级的层级。甚至有一些不可控的情况会导致域名解析出来一个错误的IP地址。
为了提高域名解析速度,以及减低域名污染风险,我们可以使用HTTPDNS的方式来进行IP获取。也可以设计一套IP直连方式获取域名IP池机制。
在APP启动后检查更新DNS服务IP的更新,域名IP池的更新,以及对IP池中的IP进行测速,选择网速较好的IP。在使用IP直连请求时,需要修改request的host,以及证书校验的host。
(2)链接耗时
建立连接需要的耗时较长,如果能够利用长连接可以保持的特性,那么这块的耗时优化非常可观。
优化这块需要后端支持,我们可以设计一个通道API,将多个域名的请求放在同一个连接中进行请求,这块需要网络库层和后端进行协议开发,业务端可以普遍享受到增益。
当然,我们也要考虑在通道不可用时,及时采用常规请求方式的策略。以及HTTP1.1存在对头阻塞问题,需要在HTTP2.0上才能真正起到优化效果。
request及response(download)优化
json解析在数据量不大的情况下一般耗时不会太多,如果遇到数据量特别大的情况可能就需要考虑怎么降低数据量,采用解析效率更高的库,可以参考如下网图。
YYModel原理和MJExtension类似,都是基于runtime进行动态获取属性进行赋值。前者使用了CoreFoundation更底层的方法以及内联函数的应用所以效率上得到了大幅提高。
(4)业务侧优化
- 网络请求优先级排布,通过对业务代码梳理,在启动阶段进行高优先级接口请求,对可以合并的接口进行合并,落地点销毁的请求及时取消请求。
升级HTTP2.0,利用其二进制分帧,头部压缩,head block优化的特性,降低请求数据量,提高并发请求效率
(5)弱网优化
弱网环境是移动APP经常需要面对的问题,地铁、人员密集区域、运动,都有可能导致网络请求不稳定、失败等问题。HTTP1.1、2.0都是采用的TCP连接方式,而TCP需要三次握手,断开后需要重新握手,这些会导致在弱网、运动环境持续请求失败。QUIC协议是谷歌提出的基于UDP的数据传输协议,HTTP3.0就是采用的QUIC实现机制。使用HTTP3.0进行网络请求可以享受到如下这些进步,当然这得服务端和客户端共同配合才能完成。
- 更好的链接建立方式
- 更好的拥塞控制
- 没有对头阻塞的多路复用
- 向前纠错
- 连接迁移