关键词排名优化网站,在海外做网站 卖东西,移动网站用什么建设,商城网站建设最新报价1.TCP协议的报文结构
TCP的全称为#xff1a;Transmission Control Protocol。 特点:
有连接可靠传输面向字节流全双工
下面是TCP的报文结构#xff1a;
源端口和目的端口#xff1a; 源端口表示数据从哪个端口传输出来#xff0c;目的端口表示数据传输到哪个端口去。…1.TCP协议的报文结构
TCP的全称为Transmission Control Protocol。 特点:
有连接可靠传输面向字节流全双工
下面是TCP的报文结构
源端口和目的端口 源端口表示数据从哪个端口传输出来目的端口表示数据传输到哪个端口去。 32位序号和32位确认序号 用来区分应答报文是针对发送方的哪条消息进行的应答。 4位TCP报头长度 表示TCP头部有多少个32bit(4个字节), 范围0~15 所以报头的最大长度为15 * 4 60字节 6位标志位每位标志位的值为0或者10代表标志位无效1代表标志位有效。 URG表示紧急指针是否有效 ACK应答报文段如果为1表示这个报文是一个应答报文 PSH提示接受端程序从TCP缓冲区把数据读走。 RST复位报文段表示重新建立连接 SYN同步报文段表示请求建立连接 FIN结束报文段通知对方本端要关闭了 16位窗口大小 表示接收缓冲区的空闲空间 16位校验和 发送端填充CRC校验。接收端校验不通过则认为数据有问题。此处的检验的数据不光 包含TCP首部也包含TCP数据部分 16位紧急指针 表示哪部分数据是紧急数据 40个字节头部选项 提供一些特殊的功能或者选项 比如 MSS (Maximum Segment Size): 最大分段大小 Windows Scale Factor: 滑动窗口的规模因子 Timestamps: 时间戳 NOOP (No Operation): 空操作选项 TCP设置那么多报文段的主要原因就是为了保证数据传输的可靠性。 可靠性是TCP协议的核心而且TCP不仅想保证可靠性还想让传输效率更高一点。 都说”鱼和熊掌不可兼得“可TCP全都要可想而知这TCP肯定是个硬骨头。 那么TCP是如何保证可靠性并且提高效率的呢下面就介绍TCP的一些特性。
2.确认应答
确认应答简单点说就是发送方发了一条数据接收方要确认一下是否收到数据。确认应答是保证可靠性的核心机制。
根据具体的例子会更好理解这还得从小明和小红的故事说起…
有一天小明联系小红请她看电影 小红答应了并且回复了好呀好呀。 小红的回复就相当于应答报文ACK报文(Acknowledgement)。 通过小红的应答小明就知道小红收到了消息。
两个人看了电影后感情进一步提升小明觉得机会来了过了几天又发消息给小红。 小红原本的回答
但是在网络中先发的消息很可能后到结果小红的回答变成了 这给小明开心坏了虽然不能看电影但是可以做自己的女朋友这不是血赚吗 为了解决这个问题就要引入序号和确认序号。 这样小明就知道小红什么意思了。 小明已经哭晕在厕所里了。 但是TCP里的序号和确认序号还跟上面的例子不一样。 下面来看看TCP的序号和确认序号是怎么回事
TCP为每个字节都进行了编号。 TCP发送端发送带序号的报文接收端返回带确认序号的报文。
ACK应答报文的确认序号跟发送过来的序号是不一样的。ACK应答报文的序号是:发送方发送过来的所有数据最后一个字节的下一个字节序号。 就拿上面的例子来说发送方总共发了100个字节这一百个字节最后一个字节的序号是100所以应答报文返回的是第100字节后的一个字节确认序号就是101了。
上面例子中应答报文确认序号的含义 小于101序号之前的数据已经收到 向发送方索要从101序号开始的数据
3.超时重传
在讲超时重传之前还得知道为什么要超时重传原因是丢包。 像平时打游戏丢包就会变得一卡一卡的那为什么会丢包呢 网络中的数据是要经过很多设备的各个设备不断转发数据最终才传到目标主机那里去。 某一个时刻某个设备流量达到峰值的时候数据再传过来就可能导致丢包了。 1.接收方没收到发送方的数据。
发送方在一定的时间间隔没有收到ACK应答报文就会重新发送数据。
2.接收方收到了数据但是发给发送方的ACK应答报文丢了!
接收方收到了数据但是ACK应答报文丢了发送方由于收不到ACK应答报文然隔了一段时间又重新发数据给接收方。
注意 在第2种情况下接收方收到了两次数据TCP会在接收缓冲区里根据收到数据的序号把数据去重。 如果发生了多次丢包多次重传每次重传的时间间隔都会变大而且累计到一定的次数就会认为接收端异常直接关闭连接。
这里拿具体一点的数字举例子比如 从间隔1S重传到间隔2S重传到间隔4S重传… 重传的次数累计到了10次直接关闭连接。
4.连接管理(三次握手四次挥手
在进行数据传输之前TCP还必须进行连接进行三次握手。 握手(Handshake)指的是通信双方进行一次网络交互。 三次握手指的是主机与主机之间进行三次交互互相记录对方的信息这就建立了连接。
TCP协议报头中有这六个标志位一个标志位占1位。 这六个报文段默认为0如果为1则有特殊含义。 SYN这一位为1则表示当前TCP数据报是同步报文表示申请连接 ACK这一位为1则表示当前TCP数据报是应答报文 三次握手
A向B发出SYN报文第一次握手B收到A发来的SYN同步报文然后返回SYNACK报文这个报文中SYN和ACK的标志为都为1。这是第二次握手A收到SYN ACK报文再返回ACK应答报文第三次握手
这三次握手的过程确定了双方的接收能力和发送能力是否正常。 如果都没问题接下来就可以传输数据了。
注意 三次握手的过程全都由内核来完成应用程序干预不了。 SYN报文和ACK报文都是由内核自动发送的。 当我们在进行TCP网络编程时还没socket.accept()时连接早已建立好了。 执行socket.accept()的时候才从操作系统内核把连接拿出来。 断开连接的时候要进行四次挥手。
A向B发送FIN报文第一次挥手B收到A的报文并且回复一个ACK报文第二次挥手过了一段时间后B向A发送FIN报文第三次挥手A收到B的报文并且回复一个ACK报文第四次挥手
注意 1.四次挥手中发送FIN报文是由应用程序来控制的 ~~~ 当执行socket.close()的时候才会发送FIN报文。 2.ACK报文则是由内核自动发送的。
5.滑动窗口
TCP不仅要保证可靠性还要保证效率。 为什么需要滑动窗口且看下图 A发送数据然后等B端的ACK 假如等了0.3s0.3s过后发送端收到了ACK了再发送下一个数据。在此期间A端白白等了0.3秒。是不是可以利用这0.3秒的时间再发几条数据呢 所以就有了滑动窗口就是批量传输批量传输不是无限地发送数据而是发送到一定的程度就等待ACK。而且是发送方收到一个ACK就立即发送下一条数据发送方批量等待的数据是保持不变的。发送方批量等待的数据的数量就称为窗口大小。
举个例子
1.A向B发送四个段的数据每段1000个字节。 第一段第1-第1000字节 第二段第1001-2000字节 第三段第2001-3000字节 第四段第3001-4000字节 这四段数据无需等待ACK直接发送。 2.B收到数据后返回第一个ACK。 3.A收到ACK后继续发送数据。 4.B发送第二个ACK。
5.A收到第二个ACK继续发送下一条数据。 一直下去如此往复
注意
在此过程中发送方等待应答的数据一直都是4000个字节即窗口大小一直保持在4000个字节。操作系统内核为了维护这个滑动窗口需要开辟 发送缓冲区 来记录当前还有哪些数据没有应答只有确认应答过的数据才能从缓冲区删掉窗口越大则网络的吞吐率就越高
如下图 当B发给A一个ACKA收到ACK之后就会继续发送数据期间这个窗口的大小是不变的而且是滑动的。 继续滑动: 批量传输的过程中出现丢包该咋办毕竟TCP还是以可靠性为主的保证可靠性是TCP至始至终的目标。 在这里丢包可分为两种情况 1.接收方收到了数据但是返回给发送方的ACK丢了。 这种情况下无所谓等到下一次ACK成功发送的时候发送方根据确认序号就知道数据有没有发送成功。 虽然确认序号为1001的ACK丢了但是确认序号为2001的ACK发送方收到了。
发送方根据这个确认序号就知道第2001字节之前的数据已经发送成功了。 这里假设发送方窗口大小为4000字节发送方继续发送数据 上图中一次发了两条数据4001-5000字节和5001-6000字节。
发送方原本的窗口 滑动之后的窗口 2.发送方向接收方发送的包丢了。
接收方所做的处理。
如上图发送方发送的1001-2000字节的数据丢了。 这里接收方不会因为接收到的是2001-3000字节就返回确认序号为3001的ACK。 而是继续返回确认序号为1001的ACK。
当返回了三次确认序号为1001的ACK之后发送方就知道了1001-2000字节的数据可能丢了。然后发送方继续发送1001-2000字节的数据。
接收方返回确认序号为7001的ACK。 这里不是返回确认序号为2001的ACK因为接收缓冲区里已经有了第7001字节之前的数据。
6.流量控制
在滑动窗口中我们说窗口越大效率越高。但是如果一下子发太多了把接收方缓冲区直接干满了。接下来如果继续发送数据就会丢包。所以流量控制就是为了防止数据发送太快而导致丢包。
在TCP报文结构中有16位窗口大小的报文段。 当ACK这个标志位为1的时候窗口大小就会生效这个窗口大小表示的是接收方缓冲区里还剩的大小0~65535字节。
下面具体说明 1.发送方批量发送数据接收方把数据放到接收缓冲区中。 2.接收方返回ACK窗口大小为1000发送方继续发送数据接收方再把数据放到缓冲区中。
3.此时缓冲区满了返回的ACK中窗口大小为0发送方不会发送数据了。 4.一段时间过后发送方会发送窗口探测报文然后接收方继续返回缓冲区中的窗口大小。
5.缓冲区一部分数据被取走了。
6.发送方继续发送探测报文得知缓冲区有空位了。 7.继续发送数据。
7.拥塞控制
滑动窗口的大小取决于流量控制和拥塞控制。 流量控制衡量了接收方的处理能力。拥塞控制衡量了传输路径的处理能力。
在网络中数据是要经过很多节点的。 如果中间任何一个设备达到处理能力上的瓶颈都会影响整个网络的传输。
拥塞控制要做的就是衡量中间经过的路径这些路径上有多少个节点每个节点的处理能力情况等等。 这里要清楚两个概念拥塞窗口和流控窗口。 这里所说的窗口不是TCP报文中的那个窗口大小而是发送方发送完数据发送方等待等待ACK的数据的数量。拥塞窗口是在拥塞控制试出来的窗口流控窗口是流量控制中得出的窗口。
实际发送方的滑动窗口大小min(拥塞窗口流控窗口)。
下面是拥塞控制的具体过程也是拥塞窗口的变化过程 1.刚开始传输会给一个非常小的窗口也叫做慢开始。 2.拥塞窗口指数级增长可以短时间到达一个比较大的值快速接近当前网络传输路径的能力瓶颈。 3.指数级增长变为线性增长避免一下子超过网络能力上限可以使得传输速度逐渐接近上限。 4.增长到一定程度出现丢包就认为当前窗口的大小已经达到了路径的传输上限。 5.立即把窗口大小降到一个很小的值继续上述过程。
8.延时应答
延时应答是啥呢就是字面上的意思等一会再应答即ACK不会立即发等一会再发。 TCP中决定传输效率的关键元素就是发送方的窗口大小而流量控制和拥塞控制共同决定了这个窗口的大小。就可以从这两个方面进行优化。而延时应答就是对流量控制做了优化。
发送方不停地发数据发到接收方的接收缓冲区里同时应用程序也在不停地从接收缓冲区里取数据。
假设接收缓冲区的大小是128KB发送方发送了64KB的数据那么缓冲区里还剩64KB的数据。
如果立即返回ACKACK报文里的窗口大小就是64KB。 发送方最多发送64KB的数据发送完就又要等下一个ACK了。
如果等一会返回ACK因为应用程序一直在从缓冲区里拿数据所以这次返回的ACK中的窗口大小大概率比64KB要大发送方就可以发多一点数据。
9.捎带应答
捎带应答顾名思义应答的时候带了一点东西就叫捎带应答。 而且捎带应答也是会延时一点时间再应答的。 如下图客户端之间的通信一般都是一问一答的。 本来ACK和应用程序的应答是不同时机的但是如果ACK延时一点发送就有可能和应用程序的应答合成一个报文这样子效率就比分两次发要高一点。 10.面向字节流
因为TCP是面向字节流的这会导致粘包问题。要明白粘包问题是啥还得看具体的例子。 如下图所示 TCP会根据序号把数据在缓冲区里拼起来缓冲区里的数据是一长串。 从小红的角度看的话他是知道小明要干什么的。因为每次小明发的消息都是以小红,小红开头的而小明就蒙了这一长串到底是啥意思。这就是粘包问题。
应用层拿到接收缓冲区的数据时无法区分一个完整的应用层数据报。很容易就会拿错应用层数据报。
解决方法 1.定义分隔符 2.约定一个应用层数据报的长度。
采用定义分隔符法拿上面的例子说明如果小明和小红每次发送数据是都会加一个\n那么就很好区分一个应用层数据报了。 小明看到\n就知道当前这个数据报到哪里结束了也就明白对方什么意思了。
平常看到的json、xml是用分隔符来实现的。
11.异常情况
1.进程关闭/进程崩溃。 进程没了socket是文件随之也被关闭但是连接还在仍然可以进行四次挥手。
2.主机正常关机。 正常流程关机会杀死所有的用户进程。也会触发四次握手如果发送端的FIN报文发过来了但是还没来得及返回ACK报文就关机了那么发送端会重新发送FIN报文发送几次之后都没有ACK返回发送方就会重置连接如果还不行干脆就释放连接了。
3.主机突然断电。 断电的是接收方。 发送方收不到ACK重传重置连接释放连接。 断电的是发送方。 接收方不知道发送方发生什么情况了。是没来得及发送新的数据还是其他情况。 TCP内置了心跳包。这个心跳包是周期性发送的。接收方会定期发送一个心跳包如果发送方没有回应接收方就能及时判断发送方是不是挂了。
4.网线断开。 网线断开和断电的情况是一样。