一、网络编程简介
真实的网络通信是基于 TCP / IP 五层网络模型实现,协议分层,自上而下,应用层-> 传输层-> 网络层-> 数据链路层->物理层,协议分层管理,规定下层协议为上层协议提供服务(接口 - API),上层协议可以直接调用下层协议,但是不允许跨层调用。除应用层以外,其余几层都被操作系统封装好了,并且提供一个传输层的接口(API)—— Socket, 那么应用层基于 Socket 开发,也就是我们常说的网络编程。
Socket ——套接字,主要提供两组传输层的协议接口。
1. 基于 UDP 传输协议的Socket 接口开发
2. 基于 TCP 传输协议的Socket 接口开发
简单讲述一下各个层级的协议主要的功能:
应用层:主要就是开发的程序需要具备一个联网,进行网络交互的功能和模式,这个一点是程序猿根据业务的实际需求设计开发的(选择使用那种传输层协议)。
传输层:主要负责数据在传输过程中的真实性,有效性等,例如:检测到数据没有传输成功那就再发一份,保证数据从源头到达目的,传输层给应用层提供服务。
网络层:主要负责数据的传输,利用IP 地址在网络中找到目的主机的位置,路由转发,提供一条可靠的传输路径。
数据链路层:主要给两个相邻的节点之间交互数据,例如将网卡中的数据交给物理层转化识别。
物理层:硬件设备,将二进制数据以各种形式传播,高低电平电信号——网线,光纤的光信号,以及广播等等。
二、TCP 传输协议简介
TCP(Transmission Control Protocol)是一种面向连接、可靠的传输协议,它在互联网协议模型中属于传输层,也是在日常开发中最广泛使用的协议,TCP 协议可以保证可靠的数据传输。
本篇博客将围绕着 TCP 协议如何保证可靠的数据传输来展开。
TCP 协议的特点:
- 面向有连接 :传输数据之前,通信双方先建立可靠连接
- 可靠传输 :TCP 协议有超时重传的机制和确认应答机制等一系列的措施,当发现连接没有问题,但数据没有成功传输的时候会重新发送数据。
- 面向字节流:字面意思,使用字节流传输。
- 缓冲区:在进行网络数据通信时,用于存储待发送或已接收数据的缓冲区,有了缓冲区的概念,可以帮助协调发送方和接收方之间的数据传输速度,并最大限度地减少数据丢失或混乱的风险……
- 传输数据的大小不受限制:字节流,流式传输,前提是有连接。
- 全双工通信:通信双方都可以同时进行信息交互,例如:电话通信
2. 1 TCP 协议报文格式
我们学习一种协议最好是从该协议的数据报开始分析。
TCP 报文的结构图:
编辑
仔细观察 TCP 数据报文结构图,我们会发现整个TCP 固定首部占20个字节,160 二进制位,但是根据我们画的结构图,所有的的节点相加只有 158 个二进制。
在数据偏移的这一行,4 + 4 + 6 + 16 = 30位, 其实有两个二进制位是被 “浪费掉了”。
TCP 报文解析:
源端口和目的端口:两个端口各占 16个二进制位 端口可以认为是应用程序的身份标识,每一个入网的程序在启动的时就会随机的绑定一个端口号, 也可以手动给程序指定一个端口号,但是注意在同一主机中端口号不可重复,另一点,就是小于等于 1024 的端口号,被称为“知名端口号”,提供给一些名气比较大的服务器使用,例如:http 80。使用端口号用于确认信息的发送方是那个应用程序,信息的接收方是那个应用程序。
序号和确认号:各占 32个二进制位 用于实现数据的可靠传输,所传送的字节流的每一个字节都会按顺序编号,保证数据传输的顺序和接收的顺序一样。序号表示当前发送的数据包的序号,确认号表示期望接收的下一个数据包的序号。
发送方: 1. 哥们早安, 2. 周末有没有兴趣出去玩啊。
接收方: 2. 周末有没有兴趣出去玩啊 ,1. 哥们早安。
这种情况很明显是不可靠的的,序列号和确认号存在的意义就在于保证数据传输的顺序和接收的顺序一样。
数据偏移量:占4 个二进制位 确定 TCP 报文头部的长度,告诉接收端的应用程序,除去TCP 头部报文,身后数据部分从何处开始。
标志位:包括ACK、SYN、FIN、RST、PSH、URG六种各占一个二进制位。
如果为标志位置为 1表示 true 的意思。
ACK用于确认收到数据包;
SYN判断通信双方是否建立了连接;
FIN用于关闭连接;
RST用于重置连接;
PSH用于提示接收方立即将数据推送给应用程序,而不是进入接收缓冲区;
URG用于指示TCP包中有紧急数据。
窗口大小:用于流量控制,的校验和值是否正确,判断数据在传输的过程中是否受到影响(例如:电磁信号干扰表示发送方能够发送的未经确认数据的最大字节数,该字段可以用于 TCP 的流量控制,下文滑动窗口详细讲述。
TCP校验和:用于检测TCP头和数据造成数据的偏差。保证数据的正确性。
紧急指针:仅在URG标志被设置为 1 时才使用,用于指示紧急数据的末尾位置。
保留:TCP报文头中的保留字段主要用于保留未来使用、兼容旧版本和防止出现错误,并为TCP协议提供了可扩展性和灵活性。
三、TCP 保证数据可靠传输的机制
3.1 确认应答
确认应答:TCP 协议中,每次发送数据,接收方都会发送一个确认应答,告诉发送方数据已接收到了,如果发送方“迟迟”没有收到确认应答,就会认为数据没有发送成功,就会将数据重新传输。
这也是 TCP 协议实现可靠传输最核心的机制。
ACK(acknowledge)标志位用于确认收到数据包,会给予通信双方一个 ACK 反馈,利用这个反馈我们就发送端就可以判断接收端已经成功接收到信息了。同时这也意味着传输“效率”会有所降低,辛苦传输过去,还得等待对方反馈回来,如果迟迟没有反馈就会尝试重新发送一份~
TCP的确认应答(ACK)是指接收方在成功接收到发起方发送过来的TCP数据包后,向发起方发送带有确认标志位的TCP报文段作为响应的一种机制。
编辑
在网络通信中也常常遇到信息“后发先至” 的情况,前两年qq 聊天就存在这个情况,我也遇到过这种情况,什么意思呢,当我给我的朋友发送一大堆消息,理论上来说,对方接受到的消息顺序应该与我发送消息的顺序一致,其实不然,消息有时候没按照我们预想的顺序来,这样就容易引起一些误会,举个例子:
编辑
网络通信中消息后发先至的原因可以有多种可能性,以下是几种可能性:
- 网络拥塞:当网络中的数据量过大时,会导致网络拥堵,从而导致一些消息被延迟发送或丢失,而其他消息在其之前被传输完毕并被接收方处理。这种情况下,即使先发送的消息比后发送的消息早,但后发送的消息可能会在先发送的消息之前到达接收方。
- 传输错误:网络传输过程中可能会出现传输错误,例如数据包损坏、丢失等等原因。如果一个数据包出现了错误,通过应答报文的反馈,发送方就需要将它重新发送,这可能会导致某些后发送的消息比先发送的消息更快地到达接收方。
- 排队延迟:当多个消息同时到达接收方时,接收方可能会将它们放入队列中进行处理。如果先发送的消息排在了后发送的消息前面,但由于其他因素(例如消息大小、处理时间等)导致后发送的消息比先发送的消息更快地被处理,那么后发送的消息就会先于先发送的消息到达接收方。
为了解决“信息后发先至” 的情况,可以对消息进行编号,给发送的消息分配一个"序号" ,同时应答报文给出“确认序号”。
编辑
TCP 协议数据传输就是引入了序号和确认序号。
TCP 协议会将每个字节的数据从前往后都进行编号,称之为“序列号”,因为TCP 是面向字节流传输的,不存在一条消息,两条消息的说法。
编辑
发送方的TCP 报文确认序号并没有多大的意义:
编辑
确认序号的规则:根据发送方发过来的数据的最后一个字节序号的下一个字节的序号。
依据序号 1001 的含义:
1. 如果应答报文的确认序号,< 1001 ,接受方给发送方透露的信息就是我已经收到
2. 接收方接下来想向发送方索要从 1001 开始的字节流。
使用这种机制,我们就可以保证数据传输的顺序,数据到达接收方也不是立马给到应用程序处理,上文提到TCP 有一个缓冲区的概念,缓冲区就可以将数据按照 “序号” 排序,即使数据在传输的过程中受到影响改变了数据传输的顺序,还有缓冲区兜底呢~ 保证应用程序读取数据,读到数据的顺序一定是和发送的顺序一样的。
如果传输一切顺利,接收方就会反馈确认应答(反馈一个“TCP 首部” 其中ACK = 1)。
3.2 超时重传
数据在传输的过程中,难免会造成 “丢包” 问题(数据缺失),好在TCP 协议有确认应答的机制,如果那一部分的数据迟迟没有反馈应答(ACK),发送方就视为刚才的那部分数据丢包了,就会重新再发一遍,如果重发了好几次都没有得到接收方的应答,就会考虑连接这方面的问题,尝试重新建立连接等,下文讲述。
超时重传:TCP协议中,如果发送方没有收到确认应答,就会进行超时重传。发送方会设置一个超时时间,如果在这个时间内没有收到确认应答,就会重新发送数据。
发送方对于丢包的判定,是一定时间内,没有收到确认应答(带有确认标志位(ACK)的TCP报文段)—— ACK = 0
这个时候存在三种情况:
1. 数据直接在传输的过程中丢失,接收方没有收到数据,也就不会反馈 带有确认标志位(ACK)的TCP报文段。
2. 接受方收到数据后,反馈带有确认标志位(ACK)的TCP报文段(TCP 首部信息包含 ACK),然后这个报文段丢了。
3. 当发送方一定时间没有接收到反馈,就会触发超时重传,然后重传的数据也丢了
第一种情况:
编辑
第二种情况:
编辑
第三种情况:
编辑
连续丢失多个数据包 “接收方无反馈” 的情况,大概率就是网络环境出现了非常严重的问题,TCP协议针对这种连续发多个数据都再丢失的情况,处理的思路是继续超时重传,但是每丢一次数据包,超时等待的时间就会越长(重传的频率降低了),如果连续多次传输超时重传都无法获取到接收方反馈的(ACK-TCP 首部信息包含 ACK),就尝试给通信双方重新建立连接,此时如果重新建立连接也是失败,TCP 协议就会放弃本次网络通信。
四、总结
TCP 传输控制协议,是互联网通信中使用最为广泛的协议,使用TCP 协议传输数据,数据安全可靠、真实性高,传输速度较快。
学习一个协议的核心先熟悉他的报文格式。
确认应答:
当接收方收到发送方的数据时,会给予发送方一个带有 TCP 首部的字段,其中ACK = 1, 表示我已经收到数据。
如果发送方一定时间内没有等到接收方反馈的确认应答,就会对该段“数据包” 进行重传,期间如果还是没有接收到反馈,发送方就会降低重传的频率,超过一定的次数,TCP 就尝试给通信双发重新建立连接,如果连接失败,就会终止本次的网络通信。
TCP 为了解决数据发送的数据和接收的数据顺序不一样,所以给每一个字节进行编码,面向字节流传输嘛,序号字段描述了当前"数据包"的序列号, 发送端的确认序号没有实际的意义,接收方反馈的确认序号描述的期望下一个“数据包”的序号,如此发送方就知道下一次对方需要 “那一段” 数据,然后就是接收缓冲区的作用,传输的数据都有了编号,就可以利用“数据包”的序号对数据进行排序,这样数据的顺序也就得到了保障。
遇到接收方数据接收成功,但反馈ACK 包丢失的情况,发送端超时重传,接收缓冲区就会对数据进行去重操作,保证应用程序拿到的数据是独一份的。