真正确立客户端和服务器建立连接的机制。为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。
为了保证通信双方都能通知对方 需释放 & 断开连接。 关闭连接时,服务端收到客户端的FIN报文时,仅仅表示客户端不再发送数据了但是还能接收数据,服务端也未必全部数据都发送给对方了,所以服务端可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,服务端ACK和FIN一般都会分开发送。
msl:Maximum Segment Life,表示TCP 对TCP Segment 生存时间的限制。可以理解为,数据包在网络上存活的最长时间,一来一回的话,就是2倍。 为什么需要超时等待? 如果服务端没有收到第四次挥手的内容,那么服务端会再次发过来,那么,客户端就需要等着,看服务端会不会再次发送数据过来,如果超过这2sml时间服务端还没有发数据过来,那客户端就认为服务端已经接收到第四次挥手发送的数据了,然后连接正式关闭。 在进行第四次挥手的时候,客户端会将ACK报文发送给服务端,由于tcp是建立在面向连接的基础上的–“有来有往”,正常情况下,服务端需要返回给客户端一个ACK数据包,告诉客户端,我已经收到你的ACK包了,但是,这样会需要一直一来一回;然而,咱们的四次挥手里面就有这样的机制,就是在被动关闭的一端(本文案例中指的是服务端),服务端在第四次挥手的时候,需要有一个超时时间等待,比如说4s,如果超出4s的超时时间,服务端没有接收到客户端发来的第四次挥手的数据,那么服务端会把第三次挥手的内容再次发送(服务端以为客户端没有收到它发的第三次挥手的内容,所以又发了一次,但是实际上客户端收到并且发送了第四次挥手的数据包),此时,我们的TIME_WAIT就发挥作用了,它是主动发起断开连接的一方的需要进行的等待实际时间,等待的作用就是,如果服务端没有收到第四次挥手的内容,那么服务端会再次发过来,那么,客户端就需要等着,看服务端会不会再次发送数据过来,如果超过这2sml时间服务端还没有发数据过来,那客户端就认为服务端已经接收到第四次挥手发送的数据了。
- tcp粘包指发送方发送的若干包数据到达接收方时粘成了一包,从接收缓冲区来看,后一包数据的头紧接着前一包数据的尾,出现粘包的原因是多方面的,可能是来自发送方,也可能是来自接收方。
- 解决方案 1、发送方 对于发送方造成的粘包问题,可以通过关闭Nagle算法来解决,使用TCP_NODELAY选项来关闭算法。 2、接收方 接收方没有办法来处理粘包现象,只能将问题交给应用层来处理。 3、应用层 应用层的解决办法简单可行,不仅能解决接收方的粘包问题,还可以解决发送方的粘包问题。 解决办法:循环处理,应用程序从接收缓存中读取分组时,读完一条数据,就应该循环读取下一条数据,直到所有数据都被处理完成,但是如何判断每条数据的长度呢? 格式化数据:每条数据有固定的格式(开始符,结束符),这种方法简单易行,但是选择开始符和结束符时一定要确保每条数据的内部不包含开始符和结束符。 发送长度:发送每条数据时,将数据的长度一并发送,例如规定数据的前4位是数据的长度,应用层在处理时可以根据长度来判断每个分组的开始和结束位置。
- UDP会粘包吗? 不会。 TCP为了保证可靠传输并减少额外的开销(每次发包都要验证),采用了基于流的传输,基于流的传输不认为消息是一条一条的,是无保护消息边界的(保护消息边界:指传输协议把数据当做一条独立的消息在网上传输,接收端一次只能接受一条独立的消息)。 UDP则是面向消息传输的,是有保护消息边界的,接收方一次只接受一条独立的信息,所以不存在粘包问题。
特性 | TCP | UDP |
---|---|---|
是否连接 | 面向连接 | 面向非连接 |
传输可靠性 | 可靠(通过三次握手、确认、窗口、重传、拥塞控制、四次挥手等机制等实现 | 不可靠 |
安全性 | 低 | 高 |
速度 | 慢 | 快 |
应用场合 | 少量数据 | 传输大量数据 |
关于TCP可以参考资料:计算机网络:这是一份全面 & 详细 的TCP协议攻略 关于http协议可以参考:计算机网络:这是一份全面& 详细 HTTP知识讲解 学习指南:这是一份详细 & 清晰的计算机网络基础 学习指南
http与https是应用层协议,他们建立在传输层的tcp协议上。http协议默认端口是80,https默认端口443。
Get请求参数是以kv方式拼在url后面的,虽然http协议对url的长度没有限制,但是浏览器和服务器一般都限制长度;Post请求参数是放在body里面的,对长度没什么限制。
http2.0跟1.0最大的提升在于多路复用、头部压缩、服务端push。
- 多路复用 http1.0如果不开启keep alive的话,每次发一个http网络请求都会建立一个TCP连接,网络请求结束后会断开连接,而且对于一个host而言,发网络请求是串行的,即使开启了keep alive,也是有限的复用TCP连接。 http2.0直接以stream的方式在一个TCP连接上发包、收包,可以实现并发发网络请求,效率更高。
- 头部压缩 http1.0不支持请求头和响应头压缩,http2.0支持。压缩头部,对于一个网络请求,可以节省至少上百个字节,这样更省流量。
- 服务端push http2.0支持后台直接给客户端推送消息。 参考资料:关于 iOS HTTP2.0 的一次学习实践
参考资料:iOS https证书双向认证的实现机制
除了用https协议传输数据,有些对数据安全要求比较高的App比如金融类App还会对参数进行签名和加密,这样可以防止网络请求参数被篡改以及敏感业务数据泄露
为了防止网络请求被篡改,一般会对请求参数进行hash,一般会有一个sign字段表示签名。
假定客户端请求参数dic如下:
{
"name":"akon",
"city":"shenzhen",
}
那么如何生成sign字段呢? 一般通用的做法是把字典按照key的字母升序排序然后拼接起来,然后再进行sha256,再md5。
- 把字典按照key的字母排序拼接生成字符串str = "city=shenzhen&name=akon"。
- 对str先进行sha256然后再进行md5生成sign。 值得注意的是,为了增加破解的难度,我们可以在生成的str前面、后面加入一段我们App特有的字符串,然后对str hash可以采用base64、sha256,md5混合来做。
为了效率,我们一般会采用对称加密加密数据,DES,3DES,AES这些方式都可以。既然要用对称加密,那就涉及到对称加密的密钥怎么生成,有如下方式:
- 最简单的方式,代码写死密钥。密钥可以用base64或者抑或算法进行简单的加密,用的时候再解密,这种方式比裸写密钥更安全。
- 后台下发密钥。后台可以在登录的时候下发这个密钥,客户端保存这个密钥后续用来做加密。由于客户端要保存这个密钥,所以还是存在泄露的风险。
- 仿照https证书校验过程,客户端生成对称加密的密钥clientKey,对参数进行加密,然后用非对称加密对clientKey进行加密生成cryptKey传给后台;后台获取到cryptKey用密钥解析出clientKey,然后再用clientKey解密出请求参数。这种方式最安全,推荐使用。
作为iOS使用最广泛的第三方网络库,AFNetworking基本上是面试必问的。笔者面试都会问,通过AF的一些问题,可以了解面试者是否熟练使用AF,以及是否阅读过AF的源代码。
如果面试者能把AF的分层架构图清晰地画出来,那至少证明面试者有阅读过AF的源码。
AFSecurityPolicy用来做证书校验的。有三种校验方式:
- AFSSLPinningModeNone 客户端不进行证书校验,完全信任服务端。
- AFSSLPinningModePublicKey 客户端对证书进行公钥校验。
- AFSSLPinningModeCertificate 客户端对整个证书进行校验。
- AFHTTPRequestSerializer、AFHTTPResponseSerializer分别用来做编码和解码。
- 编码方式有url query类型("application/x-www-form-urlencoded")、 json("application/json")、plist("application/x-plist)、MultipartFormData("multipart/form-data; boundary=")方式等。
- 解码支持NSData、json、xml、image类型。
关于AF如果再深入点可以问问具体实现细节,可以通过细节进一步考察面试者的内功。
iOS下载图片基本都用SDWebImage,这个库笔者面试基本都会问。
一、先去内存缓存找,找到了直接返回UIImage,否则走第二步; 二、去磁盘缓存里面找,找到了直接返回UIImage,否则走第三步; 三、网络下载,下载完成后存入本地磁盘和内存缓存,然后返回UIImage给调用方。
- 内存缓存key是url
- 磁盘缓存key是对url进行md5生成的。
- 对于内存缓存,在下载图片加载图片到内存时、内存收到警告时候进行清理。内存缓存基于NSCache实现的。
- 对于磁盘缓存,在App退出、进后台清理。
网络性能优化有很多手段,关于网络性能优化可以参考笔者另外一篇文章网络性能优化
如果你正在跳槽或者正准备跳槽不妨动动小手,添加一下咱们的交流群931542608来获取一份详细的大厂面试资料为你的跳槽多添一份保障。