当前位置: 首页 > news >正文

网站编辑 图片批量销售管理软件app

网站编辑 图片批量,销售管理软件app,wordpress plugin 开发,大数据营销案例分析目录 一. 再谈端口号 二. UDP协议(用户数据报协议) 2.1 UDP协议端格式 2.2 UDP报文长度 2.3 UDP校验和 三. TCP协议(传输控制协议) 3.1 TCP协议段格式 3.2 核心机制 3.2.1 确认应答 —— “感知对方是否收到” 3.2.2 超时重传 3.3.3 连接管理 —— 三次握手与四…目录 一. 再谈端口号 二. UDP协议(用户数据报协议) 2.1 UDP协议端格式  2.2 UDP报文长度  2.3 UDP校验和 三. TCP协议(传输控制协议)  3.1 TCP协议段格式 3.2 核心机制 3.2.1 确认应答 —— “感知对方是否收到”  3.2.2 超时重传  3.3.3 连接管理 —— 三次握手与四次挥手 A. 三次握手 —— 建立连接 B. 四次挥手 —— 优雅的断开连接 3.3.4 滑动窗口 3.3.5 流量控制 3.3.6 拥塞控制 3.3.7 延时应答 3.3.8 捎带应答 3.3.9 面向字节流 3.3.10 粘包问题 3.3.11 异常情况处理 3.3 其它标志位 3.4 TCP / UDP的对比 一. 再谈端口号 端口号Port标识了一个主机上进行通信的不同应用程序。 在TCP/IP协议中用“源IP”“源端口号”“目的IP”“目的端口号”“协议号”这样一个五元组来标识一个通信。 端口号是通过2个字节的无符号整数表示的取值范围0~65535实际上0端口比较特殊是一个随机设定空闲端口不会使用一般使用1~65535。其中1~1023 属于已经被预定好了的有一些知名的服务器已经提前预定了这个端口这样的端口称为 “知名端口号”。在日常开发中也会避开这些端口。说是“知名”其实这里大部分的服务器现在已经都不使用了。 但有些端口对应的服务器还是比较知名的比如 80 -- http443 -- https22 -- ssh 现在一些知名的服务器像mysqlredisrabbitmqtomcat.....使用的端口反而是1024以上的了。 什么时候会涉及到一个进程服务器绑定多个端口呢  编写的服务器肯定需要首先绑定至少一个端口和客户端进行交互  -- “业务端口”服务器运行过程中希望能够对这个服务器的行为进行一些“控制”比如让服务器重新加载某个数据 / 某个配置 / 修改服务器的某个功能也可以通过网络通信完成上述功能。此时就可以让服务器绑定另一个端口通过这个端口编写一个客户端给服务器发送一些“控制类”请求  -- “管理端口”当需要针对服务器运行状态进行检测和调试或查看服务器运行中某个关键变量的数值......千万不能用调试器来调试使用调试器一旦调试这个服务就会使服务器的一些线程被阻塞住无法正常为客户端提供服务了可以通过日志进行打印调试但是不方便还需要修改代码并且重启服务器。此时可以让服务器绑定另一个端口然后实现一些相关的打印关键变量的逻辑客户端发送对应的调试请求  -- “调试端口” 二. UDP协议(用户数据报协议) 2.1 UDP协议端格式  网络通信中UDP报文内容涉及到四个关键信息1源端口发送数据包的端口号  2目的端口接收数据包的端口  3UDP报文长度  4UDP检验和 UDP报头总共8字节固定长度。报头中的四个字段没有固定分隔符而是通过长度进行区分。 端口号是在传输层的概念使用2个字节长度表示端口号这也是端口号范围在0~65535的原因如果使用了一个更大端口就会在系统底层被截断。  2.2 UDP报文长度  UDP报文长度就是 “报头长度载荷长度”报文长度单位是“字节”比如 报文长度是1024指的是整个UDP数据包大小是1024 字节由于是2个字节来表示长度0~65535因此数据包的最大值约为64KB。如果使用UDP协议传输一个很大的数据就会在底层传输时进行数据截断既不会拆分数据也不会合并数据。UDP协议本身并没有限制数据包的大小但是底层网络协议如IPv4会限制数据包的大小。 不拆分数据UDP不会像TCP那样自动拆分大数据块为多个数据包。如果应用程序发送的数据超过了网络层的最大传输单元MTU那么这个数据包可能会在网络上被分片。这是由网络层如IPv4处理的而不是UDP层。UDP只是简单地发送整个数据包不管它的大小。不合并数据UDP也不会合并多个数据包。每个UDP数据包都是独立的包含自己的源端口、目标端口、长度和校验和信息。接收端接收到的是一个个独立的UDP数据包不会将它们合并。 针对上述情况有如下两个方案 把一个大的数据包拆成多个分别进行传输很快被否定。因为实现分包与组包的过程充满不确定性非常复杂。网络传输本身存在不确定性包括包的接收顺序、包是否在传输过程中丢失等问题就需要花费更大的成本解决这也问题直接使用TCP。因为 1TCP对于长度本身没有限制    2TCP自身带有可靠传输机制对于整体的通信质量也是有利的    3代码修改成本比较低 因此以后在使用UDP协议传输数据的时候一定要留意UDP报文长度大小是否在64KB以下。 2.3 UDP校验和 校验和/检验和checksum网络传输过程中非常容易出现错误电信号/光信号/电磁波等信号易受到环境的干扰使里面的传输信号发生改变比特翻转 1 - 0 0 - 1由于现在通信技术不断发展在地面上发生比特翻转的概率比较低在太空中比特翻转的现象会更加严重。 校验和存在的目的是为了能够发现或者纠正传输过程中出现的错误。就可以给传输的数据中引入 “额外的信息 - checksum” 用来发现/纠正传输数据的错误。 如果只是发现错误携带的额外信息就少如果想要纠正错误携带的额外信息就多要消耗更多的带宽。UDP的校验和是用来发现错误如果有错误就会将数据包丢弃不会让对方重发。 校验和的工作原理    结合内容 / 内容片段生成校验和如果出错的数据没有被校验和检查出来这个情况也是可能发生的但是一个良好的校验和算法可以让上述问题的可能性非常低。    UDP使用简单有效的方案 —— LRC校验和纵向冗余校验把UDP数据报整个数据都进行遍历分别取出每个字节进行累加。由于整个数据可能很多加着加着就可能结果溢出溢出也没关系重点不关心最终加和是多少而是关心校验和的结果是否在传输中发生改变。 例如传输一个UDP数据报    如果传输过程中数据变了校验和变成了checksum3此时接收方计算得到校验和checksum4此时checksum3大概率不等于checksum4。  在计算校验和的过程中是否可能出现两个不同的数据生成的校验和相同呢—— 可能会存在但是概率很低。除了LRC之外还可能会用到一些其他的算法计算校验和。 另外两个典型的算法MD5 和 SHA-1二者都是基于MD结构的哈希函数通过一系列的压缩函数来处理消息。此处简单讲解一下MD5算法背后的实现过程是一个“数学过程”仅需了解特点即可 MD5算法特点 定长无论输入的字符串长度多长算出的结果都是固定长度  -- 适合做“校验和算法”分散输入的内容哪怕只有一点点发生改变得到的md5值都会相差很大  -- 适合做“hash算法”不可逆MD5是一个单向散列函数这意味着从哈希值无法推导出原始消息内容  -- 适合作为“加密算法” 三. TCP协议(传输控制协议)  3.1 TCP协议段格式 1源端口和目的端口 大小各16位共32位作用标识发送和接收TCP段的端口号。这些端口号与IP头部中的源IP地址和目标IP地址结合唯一地标识了网络中的每个TCP连接。 2序列号seq -- Sequence Number 大小32位作用在TCP连接中每个字节都按顺序编号。序列号描述了载荷部分第一个字节的序号是多少。 3) 确认号ack -- Acknowledgment Number 大小32位作用期望收到对方下一个报文段的第一个数据字节的序列号。确认号用于确认已成功接收的数据。在“确认应答”核心机制中发挥重要作用 4首部长度 / 数据偏移 大小4位作用TCP报头的大小不包括载荷以32位字4字节为单位。TCP来说报头长度是可变长的4个比特位表示的数据范围0~15因此数据偏移的最大值为15表示TCP报头长度最大为60字节。这个字段之所以重要是因为它帮助接收方确定TCP头部在哪里结束以及载荷数据从哪里开始。这样接收方可以正确地解析TCP头部中的控制信息并提取出载荷数据交给上层应用程序处理。 1. 首部长度/数据偏移不会表示载荷的长度是否意味着TCP携带的载荷部分是没有限制的呢—— 不是    TCP载荷的大小具体取决于网络环境和TCP连接的协商结果。限制TCP载荷大小的因素跨越了链路层、网络层和传输层。每个层都有其自己的限制这些限制共同作用于最终的数据包大小。通常这些限制是由链路层的MTU和网络层的总长度字段所设定的而传输层的TCP协议则最终通过MSS选项来适配这些底层限制决定TCP的载荷长度。    MSSMaximumSegmentSize最大段大小是指在不进行分片的情况下网络层可以传输的最大数据量。MSS的值通常由路径MTU最大传输单元决定并减去TCP和IP头部长度。    2. 如果一次发送的数据超过限制怎么办—— 分包发送    TCP是面向字节流的一个TCP数据包和下一个TCP数据包携带的数据天然就是“可拼装的”。    比如要传输一个特别大的数据传输过程中本身就会通过多个TCP数据包携带。这些TCP数据包彼此之间携带的载荷都是可以在接收方自动被拼起来的不像UDP存在传输的上限。    使用UDP传输大数据就需要考虑调用一次send操作参数是否超过64KB超过64KB就不行使用TCP的话就没关系可以调用一次write也可以调用多次write无论如何进行write在网络传输和对端接受角度来看是没差别的因为TCP是面向字节流的 5保留位Reserved 大小6位作用保留给未来使用目前必须设置为0。如果未来某一天TCP需要新增属性/或者某个属性的长度不够用就可以把保留位拿出来用作对应的作用TCP的结构不需要发生大的改变的这样的升级就会容易很多了充分吸取了UDP的教训UDP报文长度字段无法扩展了 6选项Options 大小可变长度以4字节为单位作用用于提供额外的通信控制信息如最大报文段长度MSS、窗口缩放、选择性确认SACK等可以有也可以没有这是TCP报头变长的主要原因。 7标志位与TCP的核心机制有关 3.2 核心机制 TCP最重要的就是“可靠传输”保证数据尽可能到达对方1发送方发送数据之后能感知到对方是否收到    2发送的数据如果丢失了发送方能够进行重试 3.2.1 确认应答 —— “感知对方是否收到”  在讲解“确认应答”机制之前先详细说说TCP的序号    由于TCP是面向字节流的实际上编号并非是按照“第一条、第二条....”这样的方式编排而是按照“第一个字节第2个字节....”的方式。每个字节都有一个独立的编号字节和字节之间编号是“连续递增”的。    按照字节编号这样的机制就称为“TCP的序号”每一个TCP数据包的序号代表TCP数据包载荷中的第一个字节的序号。序列号用于标识传输的每个字节以便接收方可以正确地重新组装数据流并处理乱序或重复的数据包序号只是针对TCP数据包携带的载荷进行编号的TCP报头不参与 序列号特点 唯一性每个TCP连接的序列号都是唯一的即使在不同的TCP连接中序列号也不会重复。随机化为了提高安全性现代TCP实现通常会使用一个初始序列号ISN这个序列号是随机生成的而不是从0开始有助于防止序列号预测攻击。单调递增一旦确定了ISN后续发送的每个数据包的序列号都会基于ISN递增。每个数据包的序列号是相对于ISN的偏移量。例如如果ISN是1000并且发送了一个包含100字节的数据包那么该数据包的序列号将是1000下一个数据包的序列号将是1100依此类推。 在TCP协议中“确认应答”机制主要是为了应对不可靠的网络传输问题如数据包丢失、后发先至、乱序到达、网络拥塞等。 比如在网络通信没那么发达的时候一条短信是非常容易发丢的。当A给B发一条短信时如果B收到短信就会给A发送一条回复的短信于是根据这条回应就知道A成功发送了短信。 像B发送给A的这条回复短信在TCP协议中就称作是“应答报文”acknowledge缩写为“ACK”。在应答报文中“确认序号”表示接收方期望收到的下一个TCP数据段的序列号。 数据传输中接收方在处理完数据段后会发送一个确认应答报文ACK给发送方。确认应答中包含确认序号这个序号是接收方期望从发送方收到的下一个数据段的第一个字节的序列号表示的含义是小于这个确认列号的数据都收到了。TCP引入序列号和确认序号 目的是使应答报文和传输的数据对应上。  如果是普通报文序号是有效的确认序号是无效的设置ACK0如果是应答报文序号和确认序号都是有效的设置ACK1这是另一套编号的体系和传输的数据的序号不是一套的 除此之外序列号还能够解决网络中数据包“乱序”的问题。在网络传输中很有可能发生“后发先至”的问题。比如 网络传输中的“后发先至”问题也称为“乱序交付”是指在网络中先发送的数据包称为“先发”数据包在到达目的地时可能会比后发送的数据包称为“后发”数据包晚到达。这种现象在IP网络中是可能发生的以下是一些导致后发先至问题的常见原因 不同的路由路径数据包可能会通过不同的路由路径到达目的地。如果后发的数据包选择了更快的路径或者路径上的网络拥塞较少它可能会先于先发的数据包到达。网络拥塞网络中的某些部分可能会出现拥塞导致数据包在传输过程中被延迟。先发的数据包可能会遇到更严重的拥塞而后发的数据包则在拥塞减轻后发送因此先到达。 后发先至是客观的情况无法改变但可以给传输的数据添加“编号”通过编号区分出数据的先后顺序。 TCP解决乱序到达的机制     1. 分配序列号TCP为每个数据包分配一个唯一的序列号。序列号标识了数据包中第一个字节的编号这样接收方就可以根据序列号来正确地重新排序数据。     2. 接收数据包当TCP接收到数据包时它会检查数据包的序列号。如果序列号是期望的下一个序列号数据包就会被接受并传递给应用层。如果数据包的序列号不是期望的下一个序列号这意味着数据包可能是乱序到达的。     3. 缓冲乱序数据包TCP接收方维护一个“接收缓冲区”用于存储乱序到达的数据包。这些数据包不会被立即传递给应用层而是保存在缓冲区中直到所有缺失的数据包都到达并可以按顺序处理。     4. 确认机制TCP使用累积确认机制这意味着接收方只会确认最后一个按顺序接收到的数据包。即使后续的数据包已经到达只要它们不是按顺序的就不会被确认。 3.2.2 超时重传  实际上网络传输不会一帆风顺而是可能出现“丢包”的情况。那么为什么会丢包呢 产生丢包的原因有很多种比如1数据传输过程中发生了比特翻转收到这个数据的接收方/中间的路由器等计算的校验和对不上就会把这个数据包丢弃掉不继续往后转发/不交给应用层使用。    2数据传输到某个节点路由器/交换机)这个节点负载太高了某个路由器单位时间只能转发N个包此时是网络高峰期这个路由器单位时间需要转发的数据包超过N了发不过来了类似堵车后续传输过来的数据就可能被这个路由器直接丢弃掉。 发生丢包是完全随机的不可预测。 那么TCP是如何对抗丢包的呢—— 重新发一次。 假设网络丢包率10%数据包到达对方的概率是90%10%的丢包率是相当高的数字出现这个情况一般都是网络发生严重故障。此时进行一次重传两次传输至少一次到达对方的概率 1 - 10%*10% 99%。由此可见传输次数越多数据到达对方的概率就越大。 是否丢包需要通过应答报文来区分收到应答报文说明数据没丢包没收到应答报文就说明数据丢包了。 数据在网络传输是需要消耗时间的“没收到应答报文” 可能是1暂时没收到一会儿就收到了   2永远都收不到    因此为了区分上述情况发送方发送数据之后会给出一个“时间限制”超时时间。如果在这个时间限制之内没有收到ACK就视为数据丢包了。 发送方无法区分是上面的哪种情况因此发送方都会在达到超时时间之后重传数据。 针对确认应答丢包的情况此时主机B就受到了 两份一样的数据。如果传输的数据是“扣款”这样的请求不处理这种情况就会出问题。    TCP针对上述情况做了处理接收方有一个接收缓冲区收到的数据先进入到缓冲区中后续再收到数据就会根据序列号在缓冲区中找对应的位置排序。如果发现当前1~1000的数据已经在缓冲区中存在了就直接把新收到数据丢弃掉。确保应用程序调用read读出来的数据是唯一的不重复的。 超时重传的时间设定 这里的时间不是固定值而是动态变化的。发送方第一次重传超时时间是t1。如果重传之后仍然没有收到 ACK还会继续重传。第二次重传的超时时间是 t2其中 t2 t1。    每多重传一次超时时间的间隔就会变大重传的频次就会降低。因为经过一次重传之后就能让数据到达对方的概率提升很多再重传一次又会提升很多。反之如果重传几次都没有顺利到达说明网络的丢包率已经达到了一个非常高的程度说明网络发生了严重故障大概率无法继续使用了重传再快也没意义了。    重传也不会无休止的进行当重传达到一定次数之后TCP不会尝试重传就认为这个连接已经断开了。此时TCP会先尝试进行 “重置/复位连接”发送一个特殊的数据包—— “复位报文RST”。RST报文不需要接收方确认发送方发送RST后TCP就会立即单方面放弃连接连接就是通信双方各自保存对方的信息发送方释放掉之前保存的接收方的相关信息这个连接就没有了 再谈TCP可以自动拼装数据包的关键点 有序性由于序列号的存在接收方可以知道每个段在数据流中的位置从而可以按照正确的顺序重组数据。可靠性确认应答和重传机制确保了所有数据最终都会到达接收方即使某些段在传输过程中丢失或损坏。缓冲区管理接收方维护一个缓冲区用于存储乱序到达的段直到所有缺失的段都到达并可以按顺序拼装成完整的数据。端到端通信TCP提供端到端的通信服务这意味着它负责在整个网络路径上维护数据的完整性和顺序而不是依赖每个中间节点。 3.3.3 连接管理 —— 三次握手与四次挥手 A. 三次握手 —— 建立连接 次数网络通信交互的次数握手/挥手形象的比喻指传输一个不携带任何业务数据只有报头没有载荷的数据包 建立连接是一个“双向的操作”A需要给B说我想和你建立连接A想保存B的信息B也需要给A说我也想和你建立连接B想保存A的信息。三次握手确保了双方都准备好了数据传输从而提高了连接的可靠性。 流程简图  SYN -- synchronization此处是同步的意思。此处的同步可以延伸成客户端希望与服务器统一步调来完成后续的传输。 三次握手的意义何在 1投石问路初步验证通信的链路是否畅通这是进行可靠传输的“前提条件”排除一些可能存在的故障。 比如 地铁也会进行“链路畅通的验证”在地铁开始的第一班车之前会先空跑一趟排除在停止运营阶段可能出现的一些路线上的故障。 2确认通信双方各自的发送能力和接收能力是否都正常这也是可靠传输的“前提条件”。 比如在联机打游戏的时候双方需要确认一下彼此的耳机与麦克风是否都正常。 3让通信双方在进行通信之前对通信过程中需要用到的一些关键参数进行协商。 比如TCP通信时起始数据的序号就是通过三次握手协商确定的。换而言之TCP序号并不是从1开始的。每次建立连接TCP的起始序号都不同而且故意差别很大。 对于B来说需要区分当前收到的数据是“本朝”还是“前朝”的 —— 给每个连接协商不同的起始序列号。如果发现收到的数据和起始序列号以及和最近收到的数据序列号都差别很大的话就视为这个数据就是“前朝”的数据。 总结 进行TCP三次握手的原因 投石问路验证通信路径上是否畅通验证通信双方的发送能力和接收能力是否正常确保双方都准备好数据传输并且能够互相确认协商重要的参数比如同步TCP连接中的起始序列号以便后续的数据传输能够正确地被识别和处理防止旧的连接请求可能因为网络延迟而延迟到达被错误地接受 B. 四次挥手 —— 优雅的断开连接 前面说到“超时重传”的时候谈到了发送RST报文“单方面释放连接”而“四次挥手”是双方都释放连接的过程即双方各自把对端的信息删除掉。断开连接不一定是“客户端主动”“服务器”也可以主动断开。 四次挥手的过程 第一次挥手 1.客户端发送FIN客户端完成发送数据后会发送一个FINFinish完成报文段给服务器。这个FIN报文段中FIN标志位被设置为1序列号字段包含客户端发送的最后一个字节的序列号加1。 第二次挥手 2.服务器响应ACK服务器收到这个FIN报文段后会发送一个ACK报文段作为响应。在ACK报文段中确认序号字段设置为客户端发送的FIN报文段的序列号加1。此时客户端到服务器方向的连接被关闭但服务器到客户端方向的连接仍然开放服务器可以继续发送数据。 第三次挥手 3.服务器发送FIN当服务器也完成了数据的发送它会发送一个FIN报文段给客户端请求关闭服务器到客户端方向的连接。在这个FIN报文段中FIN标志位被设置为1序列号字段包含服务器发送的最后一个字节的序列号加1。 第四次挥手 4.客户端响应ACK客户端收到服务器的FIN报文段后会发送一个ACK报文段作为响应。在ACK报文段中确认序号字段设置为服务器发送的FIN报文段的序列号加1。在发送完这个ACK报文段后客户端会进入TIME_WAIT状态等待足够长的时间通常是2倍的最大段生命周期MSL以确保服务器收到了确认。    * 注意当客户端发送FIN包后虽然客户端的进程可以选择关闭但TCP协议栈仍然会保持活跃并不代表TCP连接已经完全断开。客户端的TCP协议栈仍然可以在需要时发送ACK包直到TCP连接的挥手过程完全结束。  流程简图 通信双方各自给对方发送“FIN”各自给对方返回“ACK”。 为什么是三次握手四次挥手呢     三次握手三次是因为中间两次的交互合并在一起了。对于四次挥手来说中间两次不一定能合并的大概率是不能     对于三次握手来说中间的两次 ACKSYN都是在内核中由操作系统负责进行的时机都是在收到SYN之后可以合并    对于四次挥手来说ACK是内核控制的但是FIN的触发则是通过应用程序调用 close / 进程退出 来触发的。代码中socket.close -- 系统内部就是发送FIN。客户端先 close / 客户端退出都会触发客户端给服务器发送FIN报文段服务器收到FIN就会立即返回ACK内核控制的并且结束读取数据的循环。    如果close之前要执行很多逻辑消耗很多时间就会使服务器发送FIN的时间更晚。 下面是整个过程的详细图解包括了TCP的状态转换 上图中的几个关键状态需要掌握 LISTEN当服务器上的一个应用程序准备好接收进入的连接请求时它会告诉内核它想要在某个端口上监听把端口绑定好。此时该端口的TCP状态变为LISTEN。此时服务器就已经初始化完毕等待客户端发起连接请求手机开机信号良好随时可以有人来打电话了ESTABLISHED表示一个TCP连接已经成功建立。这是在客户端和服务器完成三次握手之后都会进入的状态。 CLOSE_WAIT被动断开连接的一方会进入这个状态先收到FIN的一方“等待代码执行close方法”。一般而言对于服务器上出现大量的CLOSE_WAIT状态原因就是服务器没有正确的关闭socket导致四次挥手没有正确完成。这是一个bug只需要加上对应的 close 即可。TIME_WAIT主动断开连接的一方会进入这个状态。此处的TIME_WAIT按照时间来等待达到一定时间之后连接就释放了。TIME_WAIT的时间为2MSLMSL是TCP报文的最大生存时间 为什么不直接释放而是要等待一定时间呢—— 防止最后的ACK丢包。 保留一段时间之后也没有收到重传的FIN说明刚才的ACK应该就是到了就可以释放这里的连接了。 为什么 TIME_WAIT 的时间是2MSL MSL是TCP报文的最大生存时间因此TIME_WAIT持续存在2MSL的话就能保证在两个传输方向上的尚未被接收或迟到的报文段都已经消失否则服务器立刻重启可能会收到来自上一个进程的迟到的数据但是这种数据很可能是错误的)同时也是在理论上保证最后一个报文可靠到达假设最后一个ACK丢失那么服务器会再重发一个FIN。这时虽然客户端的进程不在了但是TCP连接还在仍然可以重发LAST_ACK); 3.3.4 滑动窗口 可靠传输会降低传输的效率TCP希望能在可靠传输的基础上有一个不错的效率于是引入了滑动窗口。这里的提高效率只是“亡羊补牢”使传输效率的损失尽可能降低但不能使传输效率比UDP还高。 在TCP中滑动窗口是一种流量控制机制它允许发送方在不等待确认的情况下发送多个数据包同时也允许接收方控制发送方的发送速率以避免网络拥塞和数据丢失。  改进方案就是把“发送一个等待一个”改成“发送一批等待一批”。把多次等待ack的时间合并成一份时间。批量发送的数据越多此时效率就可以认为越高。批量发送数据的量称为“窗口大小”单位是“字节不是“条”。 批量发送了1001~5000的数据后会批量等待这组数据的ACK。当收到第一个ACK后滑动窗口会移动到ACK的确认序号处并根据ACK返回的窗口大小调整右边窗口的位置。    当收到 2001的ACK说明1~2000数据得到了应答然后立即发送5001~6000这个数据。此时等待的ACK的范围就是2001~6000四份数据窗口大小还是4000。窗口大小不变窗口处在的位置改变了。 滑动窗口移动过程 1. 初始化窗口 在TCP连接建立时双方协商初始窗口大小发送方维护一个发送窗口它表示发送方可以发送但尚未得到确认的数据的最大范围 2.发送数据 发送方开始发送数据直到达到发送窗口的边界发送的数据被标记为已发送但未确认 3. 接收确认 接收方收到数据后发送一个ACK给发送方ACK中包含下一个期望接收的数据序列号接收方根据自身的缓冲区情况维护接收窗口并通过ACK中的窗口字段告知发送方自己的接收窗口大小 4.窗口移动 当发送方收到一个ACK时它会根据ACK中的序列号和窗口字段来移动发送窗口将发送窗口的左沿移动到ACK的序列号处这表示 1 ~ACK序列号-1的数据已经得到确认可以从发送方的缓冲区中移除。窗口的左边界向右移动以反映已经确认的数据这个边界称为左沿窗口的右边界可能根据接收方报告的窗口大小向右扩展或向左收缩这个边界称为右沿 滑动窗口的前提是可靠性如果在滑动窗口传输中出现丢包怎么办 情况一数据包已经抵达ACK包丢了 解决办法不需要任何处理  批量发送数据就需要批量接收ACK。多个ACK只是丢其中一部分不可能全丢。注意确认序号表示的是收到数据最后一个字节的下一个序号进一步理解成确认序号之前的数据都已经收到了接下来发送方要发的数据就从确认序号开始往后发。虽然1001 ACK丢了但是2001ACK到达发送方收到2001ACK之后意味着2001之前的数据都已经收到了后一个ACK能够涵盖前一个ACK。 情况二数据包直接丢了 解决办法快送重传机制  如果1001~2000数据包丢了此时当B收到2001~3000的时候返回的ACK确认序号不是3001而是1001意味着B在向A索要1001的数据。    接下来B收到3001~40004001~50005001~6000....数据但对应的ACK确认序号都是1001。主机A连续收到多个1001的ACK之后主机A便意识到1001数据丢包了于是会重传1001~2000的数据。    当1001~2000重传过来了之后由于之前2001~7000数据都已经收到了1001~2000相当于补全了之前的空缺意味着1~7000的数据都收到了此时从7001开始发数据即可。    上述过程就是“快速重传”机制。 快速重传 当接收方收到一个数据包但期望的下一个数据包尚未到达时它会发送一个重复的ACK这个ACK的编号是接收方期望收到的下一个数据包的序列号。如果发送方连续收到三个这个数字可能会根据不同的TCP实现而有所不同重复的ACK它就会认为网络中有一个数据包丢失了。    上述过程能快速识别出是哪个数据丢包并且针对性的重传其他顺利到达的数据都无需重传。快速重传可以视为是“滑动窗口”下搭配的“超时重传” 滑动窗口 —— 快速重传确认应答 —— 超时重传    彼此之间并不冲突的。如果通信双方单位时间发送的数据量比较少就是按照确认应答 / 超时重传的机制如果单位时间发送的数据比较多就会按照滑动窗口 / 快速重传的机制 3.3.5 流量控制 类似于生产者消费者模型如果发送速度特别快消费数据比较慢就会使接收缓冲区满了。此时如果发送方强行发数据就会产生丢包被接收方丢弃了。因此需要让接收方的处理能力反向制约发送方的发送速度——“流量控制” 如果接收缓冲区的空闲空间越大说明应用程序处理速度比较快就可以让发送方发的快一点设置一个更大的窗口大小如果接收缓冲区的空闲空间越小说明应用程序处理速度比较慢就可以让发送方发的慢一点设置一个更小的窗口大小。 TCP中接收方收到数据的时候就会把接收缓冲区剩余空间大小通过ACK数据报反馈给发送方发送方就可以依据这个数据来设置发送的窗口大小了。 通常情况下窗口大小是在ACK报文中被发送方用来告知接收方其接收缓冲区剩余的大小即当前能够接收的数据量。接收方可以根据自己的缓冲区状况动态调整窗口大小并通过发送ACK报文将新的窗口大小通知给发送方。 窗口大小    在TCP协议中窗口大小的单位是字节。TCP头中的窗口字段用于指示发送方可以在没有收到ACK的情况下发送的数据量这个字段的值表示的是窗口的大小单位是字节。    具体来说TCP头中的窗口字段是一个16位的字段这意味着它可以表示的最大数值是2^161即 65535字节。然而通过使用TCP窗口缩放选项可以扩展这个窗口大小允许更大的窗口从而支持更高的传输速率和网络吞吐量。    窗口缩放选项是在TCP选项中定义的它允许将窗口大小乘以一个缩放因子这个因子也是通过TCP选项来协商。这样即使16位的窗口字段本身的值不变实际允许的窗口大小可以远远超过65535字节。例如如果缩放因子是7那么窗口大小可以达到最大值655352^7 4,294,967,295字节。 窗口探测包不携带业务数据载荷部分是空着的只是为了触发ACK通过这个查询接收方接收缓冲区剩余多少。 流量控制也不是TCP独有的机制其他的协议也可能会涉及到流量控制比如数据链路层中有的协议也支持流量控制 3.3.6 拥塞控制 流量控制是站在接收方的视角来限制发送方的速度的拥塞控制是站在传输链路的视角来限制发送方的速度的 假设主机B处理速度非常快此时A就可以无限速度的发送数据吗—— 当然不行! 因为中间链路上的设备可能顶不住 针对传输数据速度的问题流量控制可以使用接收方接收缓冲区剩余空间来进行衡量。 考量中间节点的情况就麻烦了 中间的节点非常多每次传输数据走的路线还都不一样中间哪个节点遇到瓶颈了都不好说中间节点传输数据不止有主机A的数据还有很多其他设备的数据 拥塞控制中把中间传输的节点视为一个整体并不关心内部的细节。 拥塞控制是通过“做实验”的方式找到一个合适的发送速度面多加水水多加面 先按照一个比较小的速度发送数据数据非常畅通没有丢包说明网络上传输数据整体是比较畅通的就可以加快传输数据的速度增大到一定速度之后发现出现丢包了说明网络上可能存在拥堵了就减慢传输数据的速度减速之后发现又不丢包了继续再加速加速之后发现又丢包了继续减速 一直持续动态变化毕竟网络环境也是一直变化的整个过程如下图所示 cwnd拥塞窗口 在TCP协议中cwnd的单位是段Segment可以理解成“份”而一个段通常指的是一个TCP数据包的大小。    具体来说cwnd的单位可以MSS在讨论TCP拥塞控制时经常使用MSS作为cwnd的单位因为它更直观地表示了可以发送的完整数据包的数量。    例如如果MSS是1460字节假设路径MTU是1500字节减去20字节的TCP头和20字节的IP头那么cwnd为10MSS意味着当前可以发送10个这样的数据包即14600字节的数据。 拥塞控制过程描述 1.链路建立三次握手 在开始数据传输之前TCP通过三次握手建立连接并初始化拥塞窗口cwnd和慢启动阈值ssthresh 2.慢启动 初始化连接建立后cwnd通常被设置为1个MSS由于当前网络是否拥堵未知刚启动的时候发数据的速度很慢ssthresh被设置为较大的值例如64KB)。窗口增长每收到一个ACKcwnd增加1个MSS。由于每个RTT往返时间可以发送多个段cwnd的增长是指数级的。转换条件当cwnd达到ssthresh时停止慢启动进入拥塞避免阶段。 3.拥塞避免 窗口调整在拥塞避免阶段每个RTT只将cwnd增加1个MSScwnd的增长变为线性的。维持状态只要网络没有出现拥塞迹象如丢包TCP将继续以这种方式增加cwnd。 4.拥塞检测 丢包事件当网络出现拥塞表现为数据包丢失通过超时或收到三个重复ACK。慢启动闯值调整发生拥塞时ssthresh被设置为当前cwnd的一半对于超时或减少到当前cwnd和接收到的重复ACK指示的窗口大小的最小值对于快速重传。 5.快速重传和快速恢复 快速重传收到三个重复ACK时立即重传丢失的数据包而不是等待超时。恢复过程当收到丢失数据包的ACK时将cwnd设置为ssthresh的值然后进入拥塞避免阶段。 6.拥塞控制循环 重复过程如果再次发生拥塞丢包TCP将重复上述过程调整cwnd和ssthresh以适应网络状况。自适应调整TCP会根据网络状况动态调整cwnd和ssthresh以找到最佳的传输速率。 流量控制会限制发送窗口拥塞控制也会限制发送窗口。这两个机制会同时起作用最终实际的发送窗口大小取决于上述两个机制得到的发送窗口较小值。流量控制和拥塞控制都是对“可靠传输”进行补充。 3.3.7 延时应答 TCP的延时应答机制是一种旨在提高网络效率的优化手段尽可能降低可靠传输带来的性能的影响。它的基本思想是不是对每个接收到的数据包都立即发送一个确认ACK而是延迟发送ACK以减少在网络中传输的ACK数量。 此时延时返回的ACK窗口大小大概率就要比立即返回的ACK窗口大小更大在这个延时的时间里会有一个消费数据的过程。 注意并不是所有的包都能延迟应答 数量限制每隔N个包就应答一次时间限制超过最大延迟时间就应答一次 具体的数量和超时时间依操作系统不同也有差异一般N取2超时时间取200ms。 3.3.8 捎带应答 捎带应答是TCP中提升性能的机制它允许在发送数据的同时附带ACK确认。这意味着当发送方有数据要发送时它可以利用这个机会来确认之前收到的数据包。这样做可以减少网络中的包数量提高网络带宽的利用率。 3.3.9 面向字节流 创建一个TCP的socket套接字内核中就会自动创建一个发送缓冲区和一个接收缓冲区 调用write时数据会先写入发送缓冲区中如果发送的字节数太长会被拆分成多个TCP的数据包发出如果发送的字节数太短就会先在缓冲区里等待等到缓冲区长度差不多了或者其他合适的时机发送出去。接收数据的时候数据也是从网卡驱动程序到达内核的接收缓冲区然后应用程序可以调用read从接收缓冲区拿数据。另一方面TCP的一个连接既有发送缓冲区也有接收缓冲区那么对于这一个连接既可以读数据也可以写数据这个概念叫做全双工。 由于缓冲区的存在TCP程序的读和写不需要一一匹配就像水流一样例如写100个字节数据时可以调用一次write写100个字节也可以调用100次write每次写一个字节读100个字节数据时也完全不需要考虑写的时候是怎么写的既可以一次read100个字节也可以一次read一个字节重复100次。 以接收缓冲区为例总结一下 定义    接收缓冲区类似于一个“阻塞队列BlockingQueue”是网络协议栈中的一个内存区域用于存储从网络中接收到的数据直到这些数据被上层应用程序读取或者进一步处理B的应用程序调用read等相关方法 功能和作用 暂存数据当数据通过网络接口到达时它们首先被存储在接收缓冲区中。这样可以确保数据不会因为应用程序未能即时处理而丢失。流量控制 接收缓冲区可以作为一种流量控制机制。当缓冲区满了时接收方可以通知发送方减少发送速率或者暂时停止发送直到缓冲区有足够的空间。处理数据包乱序网络传输中数据包可能会乱序到达。接收缓冲区可以重新排序这些数据包确保应用程序按照正确的顺序接收数据。数据完整性接收缓冲区可以确保数据的完整性即使是在网络条件不佳数据包丢失或重复的情况下通过TCP等协议的机制可以恢复完整的数据流。解耦发送方和接收方的处理速度接收缓冲区允许发送方和接收方的处理速度不匹配。即使接收方的应用程序处理速度较慢接收缓冲区也可以暂存数据直到应用程序准备好处理。 工作过程 数据到达数据包通过网络接口到达接收方的网络协议栈。存储数据数据包被解封并存储在接收缓冲区中。通知应用程序当接收缓冲区中有数据时操作系统会通知相应的应用程序读取数据。应用程序读取应用程序从接收缓冲区中读取数据进行处理。缓冲区管理随着数据的读取接收缓冲区的空间被释放可以用于存储新的数据。 3.3.10 粘包问题 首先要明确粘包问题中的“包”是指应用层的数据包在TCP的协议头中没有如同UDP一样的“报文长度”这样的字段但是有一个序号这样的字段。 站在传输层的角度TCP是一个一个报文过来的按照序号排好序放在缓冲区中。站在应用层的角度看到的只是一串连续的字节数据那么应用程序看到了这么一连串的字节数据就不知道从哪个部分开始到哪个部分是一个完整的应用层数据包。 针对“粘包问题”如何进行解决呢 —— 明确两个包之间的边界 方案一在每个应用层数据包前约定一个包总长度的字段从而就知道了包的结束位置。如果是传输二进制数据这个方案就很有用了。方案二在包和包之间使用明确的分隔符。比如 编写 TCP的 echo server时我们的做法是约定“请求”“响应” 都以“\n”结尾 —— 发送请求响应的时候专门使用println进行写数据读取请求响应的时候专门使用scanner.next按照 “\n” 进行解析。但需要确认数据内容的正文中不能包含分隔符。如果传输的数据是纯文本数据的话可使用“\n”或者“ ; ”其他的数据格式可能不适合但是可以使用ASCII码中靠前的“控制字符” 对于UDP协议来说是否也存在“粘包问题”呢—— 不存在 对于UDP如果还没有上层交付数据UDP的报文长度仍然在。同时UDP是一个一个把数据交付给应用层就有很明确的数据边界。站在应用层的角度使用UDP的时候要么收到完整的UDP报文要么不收不会出现半个的情况。 3.3.11 异常情况处理 情况一进程崩溃 看起来崩溃挺严重的实际上操作系统会进行善后。当进程崩溃的时候进程中的PCB就要被回收 -- PCB中的文件描述符表里对应的所有文件也都会被系统自动关闭其中针对socket文件也会触发正常的关闭流程TCP四次挥手 情况二主机关机 正常流程点击关机按钮此时操作系统就会先关闭所有的进程与情况一相同会进行四次挥手。 a四次挥手非常快四次挥手已经完成了关机动作才真正完成     b四次挥手没来得及完成关机就完毕了 情况三主机掉电拔掉电源  TCP正常断开指双方各自删除对方TCP异常断开指单方面删除自己的不管对面了  a接收方掉电 A给B发送的数据不会再有ACK了此时A触发超时重传。重传的数据没有响应反复多次之后A会发送一个没有载荷的TCP段RST标志位置为1接收到RST段的TCP端点会立即终止连接无须四次挥手A就能单方面释放连接了。 b发送方掉电 主机A发着发着就不发了在主机B看来不知道A是掉电了还是晚点再发。此时主机B就会给主机A发送一个不携带业务数据的探测包想要触发主机A的ACK。    如果发了探测报文之后A返回了ACK说明A没有掉电如果发了探测报文A没有返回ACK甚至连续多个探测报文A都没有返回ACK就可以与A单方面断开链接了。 这样的探测报文是周期性的同时这个报文是用来探测对方“生死”的把这样的报文也称为“心跳包”。“心跳包”是一种定期发送的小型数据包用于确认网络连接的两端是否仍然活跃以及检查连接的稳定性。 TCP内置了心跳包由于TCP内置的心跳包周期比较长秒级~分钟级应用层通常也会自行实现一些心跳包达到更快速的“保活机制”。例如在TCP连接上发送特定的应用数据作为心跳包。 情况四网线断开 与主机掉电的情况是一样的。 3.3 其它标志位 1. URGUrgent紧急标志位和紧急指针配合使用。当URG1时紧急指针能够生效紧急指针里保存的是一个偏移量指示紧急数据结束的位置。正常情况来说TCP都是按照顺序来传输数据的紧急指针就是让后面的数据插队根据紧急指针的偏移量把指定位置的数据优先发送出去。特殊场景的特殊方案不是一个通用的方案日常开发中很少直接涉及。 2. PSHPush推送标志位。当PSH1时告诉接收方应该尽快将数据推送给接收应用程序而不是等待缓冲区满也是特殊场景下的特殊方案 3.4 TCP / UDP的对比 我们说了TCP是可靠连接那么是不是TCP一定就优于UDP呢TCP和UDP之间的优点和缺点不能简单绝对的进行比较 TCP用于可靠传输的情况应用于文件传输重要状态更新等场景;UDP对于可靠性要求不高用于对高速传输和实时性要求较高的通信领域。例如早期的QQ视频传输等另外UDP可以用于广播分布式系统中。 归根结底TCP和UDP都是程序员的工具什么时机用具体怎么用还是要根据具体的需求场景去判定。
http://www.ho-use.cn/article/10818211.html

相关文章:

  • 新网站seo技术手机做任务网站
  • 做网站建设一年能赚多少钱网站定制开发公司推荐
  • 山东省建设执业师网站北京校园文化设计公司
  • 手机网站要备案吗wordpress vip查看插件
  • 破解网站后台密码有人做吗怎么导入网站源码
  • 东菀高端网站建设做网站前期需要什么
  • 手机自助建站系统随州建设网站
  • 网站怎么做图片转换网站制作难吗
  • 网站建立连接不安全项目管理师pmp报考条件
  • 公司网站备案需要什么材料做网站所需技术
  • 网站建设的内容要怎么写大型服装网站建设
  • 不要钱做网站软件男科医生免费咨询
  • 做网站的协议外贸公司的网站建设
  • 学校多语种网站建设方案成都市微信网站建设报价
  • 宿迁建站网手机直播app开发制作
  • 做网站的必备软件网上商城建站工作室
  • 南阳seo网站价格哈密地网站建设
  • 延吉 网站开发未备案网站加速
  • 高端网站改版顾问新开传奇网站新开网
  • 成都市网站建wordpress 预加载动画
  • 网站建设 青海自己免费怎么制作网站
  • 万网网站到期后续费一年多少钱赞友商城电商平台排名第几
  • 怎么做教育网站兴义城乡建设部网站
  • 网站模板修改教程网站设计的流程是怎样的
  • 自由人网站开发礼服购物车网站模板
  • 网站开源模板给小孩子做网站
  • 烟台 网站建设个人网上怎样注册公司
  • 网站被挂黑链怎么处理手机端网站开发视频教程
  • 英德建设网站浙里建系统平台
  • 建设网站需要什么硬件设施购物网站有哪些平台