美文网首页
iOS 整理-网络篇

iOS 整理-网络篇

作者: 凉秋落尘 | 来源:发表于2020-02-26 17:28 被阅读0次

    1、网络七层协议
    2、Http 和 Https 的区别?Https为什么更加安全?
    3、Https的连接建立过程
    4、三次握手 和 四次挥手
    5、TCP 和 UDP的优缺点
    6、Cookie和Session的区别
    7、Socket的原理和连接过程
    8、iOS Socket封包、粘包、拆包处理

    网络七层协议
    • 应用层:对应应用程序的通信服务的。例如HTTP,FTP。
    • 表示层:主要功能是定义数据格式及加密。
    • 会话层:它定义了如何开始、控制和结束一个会话。
    • 传输层:这层的功能包括是否选择差错恢复协议还是无差错恢复协议,及在同一主机数据流的输入进行复用,还包括对收到的顺序不对的数据包的重新排序功能。例如:TCP,UDP。
    • 网络层:这层对端到端的包传输进行定义,它定义了能够标识所有结点的逻辑地址,还定义了路由实现的方式和学习的方式。例如:IP,IPX。
    • 数据链路层:它定义了在单个链路上如何传输数据。这些协议与被讨论的各种介质有关。
    • 物理层:跟传输介质有关。
    Http 和 Https 的区别?Https为什么更加安全?

    1、HTTPS 需要向机构申请 CA 证书
    2、HTTP 属于明文传输,HTTPS基于 SSL(安全套接层) 进行加密传输
    3、HTTP 端口号为 80,HTTPS 端口号为 443 。
    4、HTTPS 是加密传输,有身份验证的环节,更加安全。

    HTTPS的连接建立过程

    HTTPS的连接过程通过对称和非对称秘钥进行加密和解密的过程,服务器通过公钥和私钥进行非对称加密,客户端生成随机数进行对称加密。

    1、客户端将随机数、安全协议版本号、加密算法表发送给服务器
    2、服务器与自己的加密算法表对比,不匹配。如果匹配,服务器发送,对称算法,公钥算法,MAC算法同时还会把数字证书和生成随机数发送给客户端。
    3、客户端验证服务器公钥合法性,如果合法则将服务器的公钥来生成一个前主秘钥,将前主秘钥,和两个随机数生成会话秘钥。并通过服务端的公钥来对前主秘钥进行非对称加密,发送给服务端
    4、服务端接收到加密信息后,用私钥解密得到主秘钥。并通过前主秘钥和两个随机数来组装会话秘钥。
    5、得到两个秘钥后,开始进行数据传输。客户端收到服务器发送来的密文,用客户端密钥对其进行对称解密,得到服务器发送的数据。同理,服务端收到客户端发送来的密文,用服务端密钥对其进行对称解密,得到客户端发送的数据。

    三次握手 和 四次挥手
    • 三次握手

      1.由客户端向服务端发送 SYN 同步报文。
      2.当服务端收到 SYN 同步报文之后,会返回给客户端 SYN 同步报文和 ACK 确认报文。
      3.客户端会向服务端发送 ACK 确认报文,此时客户端和服务端的连接正式建立。

    • 建立连接

      1.这个时候客户端就可以通过 Http 请求报文,向服务端发送请求
      2.服务端接收到客户端的请求之后,向客户端回复 Http 响应报文。

    • 四次挥手

      当客户端和服务端的连接想要断开的时候,要经历四次挥手的过程,步骤如下:

      1.先由客户端向服务端发送 FIN 结束报文。
      2.服务端会返回给客户端 ACK 确认报文 。此时,由客户端发起的断开连接已经完成。
      3.服务端会发送给客户端 FIN 结束报文 和 ACK 确认报文。
      4.客户端会返回 ACK 确认报文到服务端,至此,由服务端方向的断开连接已经完成。

    TCP 和 UDP的优缺点
    • TCP:面向连接、传输可靠(保证数据正确性,保证数据顺序)、用于传输大量数据(流模式)、速度慢,建立连接需要开销较多(时间,系统资源)。
    • UDP:面向非连接、传输不可靠、用于传输少量数据(数据包模式)、速度快。
    Cookie和Session的区别
    • cookie数据存放在客户的浏览器上,session数据放在服务器上。
    • cookie相比session不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session。
    • session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。
    • 单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。而session存储在服务端,可以无限量存储
    • 将登录信息等重要信息存放为session;其他信息如果需要保留,可以放在cookie中
    Socket的原理和连接过程

    Socket(套接字)网络上两个程序通过一个双向通信连接实现数据交互,这种双向通信的连接。Socket可以支持不同的传输协议(TCP或UDP)。
    是支持TCP/IP协议的网络通信的基本操作单元,包含进行网络通信的必须的五种信息:连接使用的协议、本地主机的IP地址、本地进程的协议端口、远程主机的IP地址、远程进程的协议端口。

    Socket连接过程:
    1、客户端调用socket,绑定服务器的ip和端口号,发送一个SYN报文,进入阻塞等待。
    2、服务器使用socket,监听状态,等待客户端的连接请求并阻塞当前进程。
    3、服务器收到报文,发送ACK确认。
    4、客户端收到确认双方开始进行数据传输。(TCP,UDP)
    5、通讯结束后关闭socket,关闭连接状态

    iOS Socket封包、粘包、拆包处理

    我们在使用Socket时,理论上可以正常通信,但是因为防火墙,传输速度,网络等原因,数据传输过程中会可能出现,socket连接中断,丢包,粘包等情况的方式。因此,发送socket的过程就是封包,拆包,处理粘包问题。

    • 封包

    socket的报文格式:服务号(4bytes)+长度(4bytes)+数据

    我们在转化为二进制数据传输的协议需要依照这样的格式进行传输。报头4个字节长度的空间,用来存储服务号转换成的二进制数据;然后4个字节则是表示数据的总长度的二进制;最后是要传输的数据二进制格式。

    在IOS中,同样的发送数据需要将同样的数据转化为二进制,发送出去。例如使用CocoaAsyncSocket进行发送socket时:

        NSString * strJson  = [[NSString alloc] initWithData :data encoding :NSUTF8StringEncoding];
        Cs_Connect *connect = [Cs_Connect new];
        connect.serverID    = 1;
        connect.message     = strJson;
        connect.length      = (int)connect.message.length;
    
        //将数据传换成二进制数据,怎么转化网上有
        NSMutableData *dataModel =  [socket RequestSpliceAttribute:connect];
        // 通过Socket发出去
        [socket sendMessage:dataModel];
    
    • 粘包

    当使用TCP进行传输时,基于TCP的socket是以字节流的方式进行传输。代表这报文块和块之间没有报文边界。
    当我们在进行两个或以上的数据一起进行TCP传输时,理想上是一块一块的接收。但是现实往往有偏差,导致数据会出现多种情况:



    1、数据D1,D2分开独立到达;
    2、数据D1,D2合成一个整体一起到达;
    3、数据D1一部分先达到,还有一部分和D2一起到达;
    4、数据D1和部分D2先到达,剩下一部分D2单独到达;

    除了第一种理想的情况,其他情况会出现数据不完整问题。

    • 拆包

    为了解决粘包问题,我们需要在拆包的时候进行粘包问题处理。
    1、获取报头的长度字段,得到数据的长度和报文D1的总长度。
    2、将数据添加并保存在缓存中。
    3、根据返回来并保存在数据中的长度和长度截取完整包并返回。
    4、删除保存在缓存并已经正常返回的数据包,再读取下一个。

        //将数据存入缓存区
        [self.readBuf appendData:data];
        
        //数据中前面有4个字节的头信息,其中前两位是固定的头长度(用处不大),后两位才是数据的长度。
        //如果大于4个字节证明有消息,因为服务器只要发送数据,必定包含头
        while (self.readBuf.length > 4) {
            
            //将消息转化成byte,计算总长度 = 数据的内容长度 + 前面4个字节的头长度
            Byte *bytes = (Byte *)[self.readBuf bytes];
            NSUInteger allLength = (bytes[2]<<8) + bytes[3] +4;
            
            //缓存区的长度大于总长度,证明有完整的数据包在缓存区,然后进行处理
            if (self.readBuf.length >= allLength) {
                NSMutableData *msgData = [[self.readBuf subdataWithRange:NSMakeRange(0, allLength)] mutableCopy];
                //提取出前面4个字节的头内容,之所以提取出来,是因为在处理数据问题的时候,比如data转json的时候,头内容里面包含非法字符,会导致转化出来的json内容为空,所以要先去掉再处理数据问题
                [msgData replaceBytesInRange:NSMakeRange(0, 4) withBytes:NULL length:0];
        
                NSLog(@"开始处理数据问题");
    
                //处理完数据后将处理过的数据移出缓存区
                _readBuf = [NSMutableData dataWithData:[_readBuf subdataWithRange:NSMakeRange(allLength, _readBuf.length - allLength)]];
            }else{
                //缓存区内数据包不是完整的,再次从服务器获取数据,中断while循环
                [self.clientSocket readDataWithTimeout:-1 tag:0];
                break;
            }
        }
        
        //读取到服务端数据值后,能再次读取
        [self.clientSocket readDataWithTimeout:-1 tag:0];
    

    相关文章

      网友评论

          本文标题:iOS 整理-网络篇

          本文链接:https://www.haomeiwen.com/subject/dtlewctx.html