免费推广网站2023mmm,列出寻找网站关键词的几种途径,wordpress网站怎么打开,html考试界面设计目录 一、协议段格式及其策略确认应答(ACK)机制6个标志位超时重传流量控制滑动窗口1、先谈滑动窗口一般情况2、再谈特殊窗口 拥塞控制拥塞窗口 延迟应答捎带应答面向字节流粘包问题 二、三次握手和四次挥手三次握手为什么是3次#xff1f;不是2、4、5、6次呢 四次挥… 目录 一、协议段格式及其策略确认应答(ACK)机制6个标志位超时重传流量控制滑动窗口1、先谈滑动窗口一般情况2、再谈特殊窗口 拥塞控制拥塞窗口 延迟应答捎带应答面向字节流粘包问题 二、三次握手和四次挥手三次握手为什么是3次不是2、4、5、6次呢 四次挥手 一、协议段格式及其策略 1、报头和有效载荷如何分离 a、提取报文前20提取首部长度字段 b、首部长度字段*4 - 20 0报头完毕有几个字节的选项 c、剩下的就是有效载荷 tcp选项部分是可变的 那些是不可靠的丢包少量、大量、乱序、重复、效验失败、发送太快/太慢、网络出问题 为什么会出现这么多不可靠的问题呢 单纯就是因为通信双方距离变长了。
发送和应答最终的呈现的是什么样子 client和server是TCP客户端和TCP服务端无论是请求还是响应双方在进行交互的时候通信发送的都是TCP报头有效载荷如果有的话
确认应答(ACK)机制
你怎么知道这个报文丢包了 就有了确认应答机制C可以并发的向网络发多个报文S也可以并发的响应回来发送各个报文的时间上就被重叠了提高发送效率 1、多个报文经过网络发送顺序不一定是收到的顺序 2、当client收到多个确认的时候client如何得知哪一个应答对应哪一个报文注定了我们想要办法给报文带上编号 每个报文都有自己的编号应答的时候也要告诉我们对应的发送方所以有确认序号。
TCP报头中必定包含序号 32位序号是client自身对报文的编号 确认序号XX-1之前的报文已经全部收到了下次发请从X编号开始发送 server如果11没收到但是12收到了代表了12之前的都收到了包括10也收到了所以11丢了并不是数据丢了而是确认应答丢了 所以可以允许少量的ACK丢失更细粒的确认丢包原因
双方交互的都是TCP报文为什么序号和确认序号不搞成一个字段为什么要搞成2个字段呢响应的时候在序号里填写11不就行了吗 只研究了C到S的方向S向C发消息的时候也可以用一个序号但是RCP是全双工的C在向S发消息C也有可能在接受S的响应S也一样未来当S收到报文之后可能即想对报文做确认又想把自己发送的数据发给C在TCP大部分在收发的时候可能存在一种情况 以S为例在响应里面即可能包含C对S发的报文的确认也有S对C发送数据把这两个压缩成一个应答/请求这就是捎带应答 32位序号S-C数据序号 32位确认序号S-C历史数据的确认 同时存在所以必须是不同的字段 比如两个人吃了吗。吃了。你吃了吗。吃了我吃的是饺子。
6个标志位
6个标志位在报头里只占一个比特位要么是0要么是1 标志位本质是什么 未来有很多的客户端会同时给S端发消息有的是请求连接有的是发送消息有的是断开连接所以服务器会在同一个时刻/时间段会收到各种各样的报文请求各种各样的报文请求都是不同的 如我是一张餐厅老板入住美团有的是来吃饭的有的是来取外卖的有的是来找东西的等待作为老板来吃饭的我就要点餐来找东西的我就要问问找什么取外卖我就问取餐号我就会根据不同的人提供不同的处理动作同样的报文是有类型的。 那么怎么标识不同的报文呢所以标志位本质是标识不同类型的报文 为什么有标志位 因为标志位本质是标识不同类型的报文就是为了标志位不同的报文反应出报文的不同。 具体标志位怎么设计的 ACK 该报文是一个确认应答报文也可能会携带数据捎带应答是一个确认应答报文就多多关注确认序号
SYN 是一个链接请求的报文1、SYN 2、SYNACK 3、ACK三次握手只要SYN被置为1了就是一个链接请求的报文
FIN 是一个链接断开的报文4次挥手
PSH 催对方让对方应用层赶紧把数据拿走 比如 现实生活中你在写作业有人问你你作业写完了我说正在做有的人说加油做有的人说赶急做明天要交所以一定情况下一些别的原因有人推你尽快做完一件事 同理通信时对方因为应用层的原因接收缓冲区的数据迟迟不拿走这时就可以把PSH置为1发过去催对方
RST TCP是为了保证可靠性TCP在进行三次握手的时候是不是一定能握手成功呢不一定成功了就一定是经过了三次握手双方链接成功双方也以为连接上了S端因为一些原因把连接断了C端不知道也有可能发送 比如S端网线断了再插上C端就又向S端发请求因为C端不知道S端断网了C端就向S端发送一个置为1的RSTS端就又向C端发送三次握手要重置连接重新发起三次握手
URG 紧急指针标志位比如TCP必须是按序到达的我们有人向缓冲区放数据有人向缓冲区的拿数据有人放有人拿这就是生产消费模型 如果我们想插队呢我们想让特殊的数据尽快的处理就有了URG告诉接收方我们报文里有紧急数据这16位紧急指针是有效的因为16位紧急指针大部分是无效的
16位紧急指针 本质是一个偏移量紧急数据在有效载荷中的偏移量 这个数据有多大呢报头里并没有标识处理因为我们的紧急数据只有一个字节所以并不用告诉我们紧急数据的大小就需要告诉我们在那个位置 URG有什么用 携带了URG的标志位就不用排队了要通过特殊的发送和接收才能收到URG有时候我们在正常上传数据我们突然不想上传了向对方发送不想上传的数据时候这个数据是要排队的还有大量的数据会紧急叫停这时候就可以带一个URG不用排队了 但是对方怎么知道我们是暂停上传还是取消上传呢 这时候就可以用1个字节的数据表示状态码1表示取消2表示暂停3表示继续 紧急指针也可以叫带外数据不走主传输流直接传输就是带外数据 如何使用recv中的flag参数有很多对应标志位 比如MSG_OOB在接收的时候不会从正常的流中接收就可以读取到紧急数据也可以使用MSG_OOB来发送
可靠性并不是对方把数据全收到就叫可靠性我发出来数据我作为发送方我知道对方收到或没收到要有回馈这也叫做可靠性我知道没发成功
TCP不关心上层传下来的是什么不关心发送缓冲区里的数据反正都是二进制数据 char sendBuffer[N] 发送缓冲区宏观是看做为一个大数组一格一格的上层传下来数据无论是结构体还是其他都是二进制上层拷到发送缓冲区中的数据天然的就有编号这个编号就是数组下标一段数据就是数组的开始和结束所以数组里的数据有人拿有人放这就是TCP面向字节流的表现
超时重传 主机A向B超时重传但是B已经收到过了A再超时重传一次所以B会收到重复报文就有了去重的功能收到重复报文也是不可靠的体现所以有去重的功能 主机A如果把数据已经发到了网络里了可是主机A不能把已经发送的数据去掉主机A一旦发送出去会对数据暂时维护一段时间会维护到还没反馈的时候 一个已经发送的数据还没回应的时候会暂时保存起来以应对超时重传
流量控制 16位窗口大小用来流量控制的防止发送方发送太快或太慢 send/write read/recv这些IO接口本质是拷贝给了发送和接受缓冲区并没有发送到网络发送过程就是把数据从C的发送缓冲区拷贝到S的接受缓冲区所以发送缓冲区所对应的传输层TCP什么时候发发多少出错了怎么办由TCP控制所以应用层的作用就是把数据拷贝给了下一层就返回了。 可是这两台机器相隔千里之外如果给对方发送数据太快对方接受来不及对方接受缓冲区满了你再发那么对端就来不及接受就把报文直接被丢弃了那么报文就丢失了所以TCP有确认应答机制可以超时重传我不怕但是站在这几个后续报文的角度我在路上都没出问题到了目的你告诉我们要被丢弃了就仅仅是你来不及接受虽然可以但是不合理这时候已经消耗了很多网络资源我没有出错是你来不及接收是因为你发的太快这种做法是比较低效的表现所以你来不及收了就要早点说嘛让发送方控制一下发送速度这种策略就是流量控制 那我们怎么样控制发送缓冲区不要发送太快呢 接收方对对方发过来的每一个数据都有一个应答我们在应答的时候就可以告诉对方我的接受能力我的发送速度是由对方接收能力来决定的对方的接受能力取决于接收缓冲区中剩余空间的大小所以 1、每个报文都有应答 2、自己是知道自己的接受能力的 所以有了16为窗口大小这就是流量控制 对方就会把剩余空间大小填到16位窗口大小里根据16位窗口决定发送方最多还可以发送多少数据
填谁的接受缓冲区的剩余空间的大小 填自己的凡是我要构建TCP报文必定是我要给对方发信息无论是发数据还是应答还是数据加应答填的都是自己的信息 所以叫做流量控制我们双方就不用担心发送太快的问题数据就不会丢失既然我们发的太快了那如果C端发的太慢了流量控制也会给你加快点提速。 比如S端还剩100kb的空间C端给S端发了S端上层立马取走了数据空间变的很大了S端立马就给C端同步的缓冲区变为4096了变的很大了C端就立马发快了
一旦校验失败了该报头和数据立马丢弃这就是真正的丢包但是不用担心可以超时重传
保留就是有时间就用 TCP在正常通信的时候来不及接受我可以给你补发但不是最优的选择是低效率的表现 当我们进行首次发送的时候我怎么知道你的接受大小怎么保证第一次发送就不会过快或过慢 双方在进行TCP的时候第一次并不是通信的时候在通信之前早就发送报文交换了在三次握手之前就至少发送一次报文交换了。 第一次交换的时候并没有有效载荷大小肯定是合适的当接收方空间满了上层还没取走发送方会不断发送窗口探测没有有效载荷当接收方被上层收走了接收方也会给发送方通知一下窗口更新
滑动窗口 收发是串行的收发效率就低下 一般是Client给server塞大量报文server给client大量响应两种方法都可能会同时存在 TCP协议可靠性是主要研究的问题但是不是全部 效率问题也是TCP考虑的问题 不管并发访问多少但是对方是由接受能力上限的所以发送方并发发送一定要在对方能够接受的前提条件下进行并发发送 所以我们发送方目前最大一次可以向对方发送多少的数据呢由对方的窗口大小决定目前这样认为
1、先谈滑动窗口一般情况
滑动窗口其实是发送缓冲区里的一部分里面的数据暂时不用收到应答可以直接发送但是不能超过对方窗口大小 滑动窗口的左侧部分数据已经发送已经确认可以被覆盖是无效数据右侧是尚未发送的数据区域在滑动窗口的数据可以直接发送但是尚未收到应答有了应答窗口就要滑动了 滑动窗口应该是多大的 和对方的接受能力有关应答报文中win大小目前 所以我们对应的谁向滑动窗口放数据 用户向尚未发送的数据区域放数据
1.1、如何理解滑动窗口 发送缓冲区当成一个char类型的数组大小与系统有关 上层拷贝下来的数据数组就天然有了编号滑动窗口就是一块数组区间本质就是由两个数组下标维护的数组区间 所以滑动窗口未来是要扩大或移动本质上就是对两个数组下标进行,这就是滑动窗口
2、再谈特殊窗口
1滑动窗口只能向右滑动吗可以向左滑动吗 不能向左因为左边数据已经发送了无意义了
2滑动窗口能变大变下吗能变0吗变0之后表示什么意思 能变大取决于对方给我通告的win大小本质就是winend能变小我在给对方一直发报文对方上层一直不接受给我的win大小越来越小所以能变小滑动窗口的大小是浮动的能变成0上层一直不接受表示对方不能在接受数据就进入流量控制的窗口探测和窗口更新
3能一直滑动吗越界怎么办 把发送缓冲区设计成环状结构所以可以把历史数据覆盖把环形区当成字节流
4滑动窗口的大小怎么更新的依据是什么 目前是根据对方的接受能力响应报头中的win大小 应答也是有序的也是按序达到应答的seqwinstart seq这就是起始位置应答的winwinend winstart win这就是更新
5滑动窗口内部的报文既然可以直接发送多个报文如果第一个丢失了呢中间的丢失了呢最后一个丢失呢 比如1000,2000,3000,4000如果1000丢了2000,3000,4000中任意一个收到了有两种情况 数据丢了应答丢了 收到2001和3001时所以1000也收到了所以应答丢了我们一点也不担心 但是数据丢了在2000和30004000给你的应答接收方收了2000,3000,4000但是接收方的ACK只能写1001 所以会收到很多重复的ACK序号TCP就能确定数据数据丢了进行补发滑动窗口就不会动一直等等超时重传补发后ACK就会一下到6001,70018001 要支持重传就必须被暂时保持起来保存在滑动窗口中 中间丢失会传化成第一个丢失所以滑动窗口中的丢失都会传化成第一个丢失 当中间某一个报文丢失了连续收到三个同样的序号ACK后就会对最近的报文做确认进行重传这就是快重传决定重传的下限即超时重传一个决定重传的上限即快重传超时重传效率会低下 快重传是收到三个同样的ACK才是快重传
拥塞控制
所以client的发送数据都会经过网络万一是网络出问题呢 TCP不仅把c和s端考虑了还考虑了网络网络中有大量的接收方和发送方都是遵守的TCP/IP协议 假设考操作系统成绩出来后有1到2个人挂科是同学的问题可是有30人只有1到2个人过了其他人都挂了这就是题的问题学校就出了教学事故所以同样是挂科挂少和挂多是不同的事情 同理如果A主机给B主机发信息只有1到2个报文丢失了这是正常的给你补上就是了如果发10000报文丢了9999报文就是网络的问题
当大量丢包的时候发送方的发送策略是什么 超时重传/快重传还是等等再发呢是等等再发一旦我们谈网络一定会有其他主机C端向S发送数据S端出现大面积丢包3给4发5给6发4和6主机也可能大面积丢包 一旦网络出现拥塞会覆盖这个网络的所有主机如果一旦超时重传所有主机也会超时重传同一时间出现大量补发反而会加重网络拥塞 发送网络拥塞了就减少发送量如果少量报文丢了就继续超时重传 发生网络拥塞了要保证 1、保证网络拥塞不能加重 2、在网络拥塞有起色的情况下尽快恢复网络通信
拥塞窗口 A向B发送1个2个3个4个报文发送了网络拥塞发送方要基本得知网络拥塞的严重程度必须要进行网络状态的探测 需要对当前的网络情况进行衡量就有了拥塞窗口超过这个拥塞窗口的大小时就可能会发生网络拥塞没有超过就小概率的发生网络拥塞 拥塞窗口就是发送方主机衡量网络健康状态的指标 拥塞窗口网络的状态是变化的衡量网络健康状态即拥塞窗口大小一定是变化的 但是作为主机的你你怎么知道网络的健康状态是什么样子的呢 尝试与探测出来的所以发送方主机一直都要想办法得到当前网络的拥塞窗口所以发送方滑动窗口 min对端主机的接受能力win网络的拥塞窗口 win_start seq; win_end min(seq_win,拥塞窗口) A主机向B发送数据一旦识别网络发生拥塞了如何设置成1呢把拥塞窗口设置成1就行了滑动窗口就成1了也不用担心滑动窗口一直在增长了
为什么用指数增长的方式增长拥塞窗口 比如在旧社会有一些地主、他们有一些土地有个地主张三有个农民李四张三来问李四你欠我房租什么时候还李四没钱还张三就说你一天给我一粒米明天二粒米后天给4粒米李四只会算短期的账给到20多天时就发现给不起了但是地主后面也发送这样太害人了就说换到1000粒时就不用还2000了就变到1001、1002了为了更压榨农民就从指数增长变为线性增长 李四为什么会给呢因为前面给的少 但是一旦过了一个临界点增长速度就快 所以慢启动就是指初时慢但是增长速度非常快是为了快速让网络恢复前期慢是为了探测但是也不能一直指数增长吧到达一个阈值就变为线性增长
慢启动的算法指数增长在增长的同时在增长到一个阈值时就线性增长这也是在不断探测新的拥塞窗口的大小 在未来的时候又发生网络拥塞就探测到了拥塞窗口的底线为24然后把下一个拥塞窗口变为1慢启动把上一次拥塞窗口大小砍到一半就是下一个拥塞窗口的阈值值为12 整个网络发送就是不断慢启动然后发生网络拥塞然后又慢启动 所以拥塞窗口会一直被os维护所以拥塞窗口一直在更新就是一直在探测指数增长和线性增长就是在探测 不断调整拥塞窗口的大小就是间接控制滑动窗口 在我们计算机中一定时时刻刻都会存在一个拥塞窗口的大小
延迟应答捎带应答
应答就是通告我的接受能力的win 我们只要给对方通告更大的win大小就能在较大概率上提高传送效率 对方可能就会更新出更大的滑动窗口大小就可以一次并发给我们发送更多的数据 你怎么给我更新出一个更大的接收窗口只要让上层尽快交付才有可能更新出更大的接收能力但是我又不知道什么时候交付 所以给上层更多的时间来进行读取 给更多时间好处就是 1、让他在这段时间尽快读取 2、如果一直在读读取更多 所以有延迟应答所以本质是为了提高效率 其实三次握手就相当4次握手因为SNY连同ACK一起发过来了这就是捎带应答
TCP的可靠性校验和、序列号、确认应答、超时重发、连接管理、流量控制、拥塞控制 提高性能滑动窗口、快速重传、延迟应答、捎带应答
面向字节流
我们把1000个数据交给操作系统os可能发生了几次刷新我们不关心而我们就只看见认为一次刷新
对于底层我们看到的二进制都是二进制流在上层读到二进制流就知道是什么意思所以就有编码操作系统并不关心协议协议本质就是阐述一个事实解释os里的二进制流 所以协议就是编码 当在读数据的时候并不是从硬件直接读到用户层在触发读的时候就是在系统调用操作系统先把数据搬到文件缓冲区里这时候read、write才起作用般了几次还是拷多少kb我们不关心你可能一次拷完了但是OS也许拷了很多次
粘包问题
TCP会存在粘包问题是因为他是面向字节流没有边界 TCP是被使用的TCP不认识二进制流但是上层认识TCP并不知道这些二进制流的意义 当TCP收到http请求发给对方也许收到了1个半2个半但是我们并不知道是不是一个完整的报文你必须要读完整的报文读不完整交给上层上层解析不出来 这种多读少读就是粘包问题所以序列化和反序列化之前先要解决粘包问题 为什么要分清报头和有效载荷就是怕粘包问题 比如蒸包子就想拿一个但是拿了多个或就一个皮所以蒸的时候会一个一个分开分开就是解决粘包问题明确包子与包子的边界 如何解决比如之前整个报文就有\r\n就以\r\n来区别报文
UDP不存在粘包问题因为UDP中携带定长报头加报文的长度有明显的边界一定是一个完整的报文不会出现半个的所以UDP直接序列化和反序列化
TCP协议只有4位首部长度没有有效载荷的长度因为他不需要能根据4位首部长度去掉报头剩下的就是有效载荷还有校验和也是按序到达的所以不需要有效长度
内存泄漏肯定是malloc和new申请空间了不还内存申请多了然后进程挂掉了曾经的那些堆空间还在不在这些内存在不在 不在了因为进程的pcd、页表、空间都是os管理的进程挂掉了os会回收的 同样的网络也是如此建立一个链接也是os帮你建立的进程退出了os会私自给你做四次挥手 关机之前进程都要先杀掉的关机前底层会自动进行4次挥手这就是为什么关机有时候快有时候慢
TCP的链接和管理的作用是由上层来做是应用层来维护的因为只有应用层才知道要连接多久
以前QQ是UDP来做的UDP不用建立连接不用维护成本你给我发消息我就给你转过去是即时通信的
面试题用UDP来实现可靠性怎么做 引入序列化保证数据顺序 确认应答确保对端收到了数据…
二、三次握手和四次挥手 服务端状态转化:
[CLOSED - LISTEN] 服务器端调用listen后进入LISTEN状态, 等待客户端连接;[LISTEN - SYN_RCVD] 一旦监听到连接请求(同步报文段), 就将该连接放入内核等待队列中, 并向客户端发送SYN确认报文.[SYN_RCVD - ESTABLISHED] 服务端一旦收到客户端的确认报文, 就进入ESTABLISHED状态, 可以进行读写数据了.[ESTABLISHED - CLOSE_WAIT] 当客户端主动关闭连接(调用close), 服务器会收到结束报文段, 服务器返回确认报文段并进入CLOSE_WAIT;[CLOSE_WAIT - LAST_ACK] 进入CLOSE_WAIT后说明服务器准备关闭连接(需要处理完之前的数据); 当服务器真正调用close关闭连接时, 会向客户端发送FIN, 此时服务器进入LAST_ACK状态, 等待最后一个ACK到来(这个ACK是客户端确认收到了FIN)[LAST_ACK - CLOSED] 服务器收到了对FIN的ACK, 彻底关闭连接.
客户端状态转化:
[CLOSED - SYN_SENT] 客户端调用connect, 发送同步报文段;[SYN_SENT - ESTABLISHED] connect调用成功, 则进入ESTABLISHED状态, 开始读写数据;[ESTABLISHED - FIN_WAIT_1] 客户端主动调用close时, 向服务器发送结束报文段, 同时进入FIN_WAIT_1;[FIN_WAIT_1 - FIN_WAIT_2] 客户端收到服务器对结束报文段的确认, 则进入FIN_WAIT_2, 开始等待服务器的结束报文段;[FIN_WAIT_2 - TIME_WAIT] 客户端收到服务器发来的结束报文段, 进入TIME_WAIT, 并发出LAST_ACK;[TIME_WAIT - CLOSED] 客户端要等待一个2MSL(Max Segment Life, 报文最大生存时间)的时间, 才会进入CLOSED状态 较粗的虚线表示服务端的状态变化情况; 较粗的实线表示客户端的状态变化情况; CLOSED是一个假想的起始点, 不是真实状态;
三次握手
connect本质就是发起三次握手 1、什么是链接 一定在OS内同时存在多个建立好的链接那么OS要不要把这些已经建立好的链接管理起来呢要管理先描述再组织OS内为了管理连接维护的数据结构 struct tcp_link{…} 创建并维护连接是有成本的要消耗内存空间和CPU资源
3次握手的过程由双方的OS系统中的TCP层自主完成 connect触发连接等待完成 accept等待建立完成获取连接 报文在路上跑收到的时间一定有差别 对于双方来说从来就不担心第一个报文和第二个报文丢失连接就没成功就没什么损失 第三次丢失就有影响只要把最后一个ACK发出去就说明连接成功了但是对于客户端来说我不知道第三次对方收到没所以三次握手就是在赌 客户端认为建立好了服务端认为没建立好客户端就可能对服务器发送消息但是服务器认为没连接就给客户端发送RST响应重置 所以客户端把连接关掉就重新进行连接所以三次握手的本质就是在赌赌对方收到第三个ACK所以建立连接成功与否是有概率的
为什么是3次不是2、4、5、6次呢
2次握手是绝对不行的凡是客户端发来的SYN服务器就认为连接成功了我拿个单片机发送海量的SYN一瞬间就把服务器的链接请求满了资源就没了海量发送SYN就叫SYN洪水 所以2次握手非常容易收到攻击 如果我们是主动发起连接的一方最后一次发送ACK是没有应答的最后一个报文是谁发的就是谁先连接如果是偶数次握手就是服务器主动发起最后一个握手如果是奇数次握手就是客户端主动发起最后一个ACK最后一个报文在网络中是要花时间的所以是偶数一定是服务器先建立好链接所以把不确定是带给服务器最后一个ACK客户端有没有收到服务器不确认。
为什么是奇数不是偶数 因为连接握手一定会发送异常一定用概率服务器遇到多个客户端发送概率是很大的但建立连接异常是不担心第一和第二次如果是偶数次最后一次是ACK承担连接的成本就嫁接到客户端那服务器端面对的是多个客户端服务器维护这个异常就是必然的对服务器不好所以就直接搞成奇数次握手对应客户端来讲就是客户端主动发起连接的主动发送的人在奇数当中都是最后一个发送ACK的人当服务器收到最后一个ACK时就会把最后一个ACK发送异常的成本嫁接给客户端服务器没收到ACK客户端认为已经连接了只需要连接重置就行了服务端的成本维护依旧低
为什么是3次 1没有明明显的设计漏洞一旦建立连接出现异常成本嫁接到clientserver端成本较低 2验证双方通信信道的通畅情况— 三次握手是验证全双工通信信道通畅的最小成本
四次挥手
四次挥手是断开连接的最小成本 CLOSE_WAIT一方想关连接一方还不想关被动关闭连接的一方就会维持CLOSE_WAIT 在服务器或客户端通信的时候一定不要忘记关闭fd不关闭fdCLOSE_WAIT会维持一段时间这个链接状态会一直存在可用资源会一直变少 主动断开的一方要进入TIME_WAIT状态 TIME_WAIT临时性状态过一会就没了这时候连接还在也可以理解成不在了是一个临界的状态服务器主动断开的一方在进入TIME_WAIT时候双方进程早就退出了但是我们的底层还是链接的也就是port号还是在使用的也就是为什么我们前面主动退出server在登录的时候要换port的原因
1、为什么要进行TIME_WAIT 保证最后一个ACK被对方收到连接建立异常断开也是可以的最后一个ACK丢了就一直等 2、为什么是TIME_WAIT的时间是2MSL? MSL是TCP报文的最大生存时间, 因此TIME_WAIT持续存在2MSL的话就能保证在两个传输方向上的尚未被接收或迟到的报文段都已经消失(否则服务器立刻重启, 可能会收到来自上一个进程的迟到的数据, 但是这种数据很可能是错误的)同时也是在理论上保证最后一个报文可靠到达(假设最后一个ACK丢失, 那么服务器会再重发一个FIN. 这时虽然客户端的进程不在了, 但是TCP连接还在, 仍然可以重发LAST_ACK);
3、sever主动关闭连接的场景 比如双11期间客户端越来越多后面又来了一个链接这是server抗不住了立马挂掉了以前的连接的客户端服务器都是主动断开的一方服务器会存在大量的TIME_WAIT这是服务器会尽快重启但是还处于TIME_WAIT状态服务器就一直等这段时间就导致服务器无法重启但是对于大公司来说服务器挂掉一会也是重大失误所以要立马重启所以有个接口setsockopt
为什么是4次挥手因为要双方确认
listen的第二个参数 三次握手会在底层自动完成 netstat -natp查看所以tcp的client和server的链接情况 telnet测试本地连接情况 没有acceptlisten的第二个参数设为1已经连接的就只有2个后面就出现SYN_RECV这些SYN_RECV就是在般连接的队列里时间非常短 TCP协议需要在底层维护全连接队列最大长度是listen的第二个参数1 比如海底捞排队门口排队就是为了时时刻刻保证自己餐厅内部资源的使用率是100%海底捞不能没有外部的队列但是如果海底捞把排队的队列越来越长人也会离开资源还浪费了还比如那店门扩大一点 所以这个队列不能太长原因 1、因为会过多消耗OS本身的资源本来是可以给sever使用的 2、队列太长client不愿意等