小林计算机网络・传输篇TCP/UDP|三次握手|四次挥手|可靠传输
目录传输层说一下tcp的头部TCP三次握手过程说一下tcp为什么需要三次握手建立连接TCP 三次握手客户端第三次发送的确认包丢失了发生什么服务端发送第二个报文后连接的状态进入什么状态三次握手和 accept 是什么关系 accept 做了哪些事情客户端发送的第一个 SYN 报文服务器没有收到怎么办服务器收到第一个 SYN 报文回复的 SYN ACK 报文丢失了怎么办假设客户端重传了 SYN 报文服务端这边又收到重复的 SYN 报文怎么办第一次握手客户端发送SYN报后服务端回复ACK报那这个过程中服务端内部做了哪些工作大量SYN包发送给服务端服务端会发生什么事情TCP 四次挥手过程说一下为什么4次挥手中间两次不能变成一次第二次和第三次挥手能合并嘛第三次挥手一直没发会发生什么第二次和第三次挥手之间主动断开的那端能干什么断开连接时客户端 FIN 包丢失服务端的状态是什么为什么四次挥手之后要等2MSL?服务端出现大量的timewait有哪些原因?TCP和UDP区别是什么TCP为什么可靠传输怎么用udp实现httptcp粘包怎么解决传输层说一下tcp的头部序列号在建立连接时由计算机生成的随机数作为其初始值通过 SYN 包传给接收端主机每发送一次数据就「累加」一次该「数据字节数」的大小。用来解决网络包乱序问题。确认应答号指下一次「期望」收到的数据的序列号发送端收到这个确认应答以后可以认为在这个序号以前的数据都已经被正常接收。用来解决丢包的问题。控制位• ACK该位为 1 时「确认应答」的字段变为有效TCP 规定除了最初建立连接时的 SYN 包之外该位必须设置为 1 。• RST该位为 1 时表示TCP连接中出现异常必须强制断开连接。• SYN该位为 1 时表示希望建立连接并在其「序列号」的字段进行序列号初始值的设定。• FIN该位为 1 时表示今后不会再有数据发送希望断开连接。当通信结束希望断开连接时通信双方的主机之间就可以相互交换 FIN 位为 1 的 TCP 段。TCP三次握手过程说一下一开始客户端和服务端都处于 CLOSE 状态。先是服务端主动监听某个端口处于 LISTEN 状态客户端会随机初始化序号client_isn将此序号置于 TCP 首部的「序号」字段中同时把 SYN 标志位置为 1表示 SYN 报文。接着把第一个 SYN 报文发送给服务端服务端收到客户端的 SYN 报文后首先服务端也随机初始化自己的序号server_isn将此序号填入 TCP 首部的「序号」字段中其次把 TCP 首部的「确认应答号」字段填入 client_isn 1, 接着把 SYN 和 ACK 标志位置为 1。最后把该报文发给客户端客户端收到服务端报文后,发送应答报文 在TCP的 [确认应答号」字段填入 server_isn 1 ,ACK 标志位置为 1 之后客户端处于 ESTABLISHED 状态。服务端收到客户端的应答报文后也进入 ESTABLISHED 状态。第三次握手是可以携带数据的前两次握手是不可以携带数据的tcp为什么需要三次握手建立连接三次握手的原因• 三次握手才可以阻止重复历史连接的初始化主要原因• 三次握手才可以同步双方的初始序列号• 三次握手才可以避免资源浪费三次握手可以阻止历史连接进行初始化三次握手的场景客户端连续发送多次 SYN都是同一个四元组建立连接的报文在网络拥堵情况下• 一个「旧 SYN 报文」比「最新的 SYN」 报文早到达了服务端那么此时服务端就会回一个 SYN ACK 报文给客户端此报文中的确认号是 91901。• 客户端收到后发现自己期望收到的确认号应该是 100 1而不是 90 1于是就会回 RST 报文。• 服务端收到 RST 报文后就会释放连接。• 后续最新的 SYN 抵达了服务端后客户端与服务端就可以正常的完成三次握手了。上述中的「旧 SYN 报文」称为历史连接TCP 使用三次握手建立连接的最主要原因就是防止「历史连接」初始化了连接。两次握手的场景在两次握手的情况下服务端在收到 SYN 报文后就进入 ESTABLISHED 状态可以给对方发送数据但是客户端此时还没有进入 ESTABLISHED 状态假设这次是历史连接客户端判断到此次连接为历史连接那么就会回 RST 报文来断开连接也就是说在RST报文到达前服务端会一直发送数据。如果采用两次握手建立TCP连接的场景下服务端在向客户端发送数据前并没有阻止掉历史连接导致服务端建立了一个历史连接又白白发送了数据妥妥地浪费了服务端的资源。同步双方初始序列号TCP 协议的通信双方 都必须维护一个「序列号」它的作用• 接收方可以去除重复的数据• 接收方可以根据数据包的序列号按序接收• 可以标识发送出去的数据包中 哪些是已经被对方收到的通过 ACK 报文中的序列号知道可见序列号在 TCP 连接中占据着非常重要的作用所以当客户端发送携带「初始序列号」的 SYN 报文的时候需要服务端回一个 ACK 应答报文表示客户端的 SYN 报文已被服务端成功接收那当服务端发送「初始序列号」给客户端的时候依然也要得到客户端的应答回应这样一来一回才能确保双方的初始序列号能被可靠的同步。四次握手与三次握手四次握手其实也能够可靠的同步双方的初始化序号但由于第二步和第三步可以优化成一步所以就成了「三次握手」。而两次握手只保证了一方的初始序列号能被对方成功接收没办法保证双方的初始序列号都能被确认接收。避免资源浪费如果只有「两次握手」当客户端发生的 SYN 报文在网络中阻塞客户端没有接收到 ACK 报文就会重新发送 SYN 由于没有第三次握手服务端不清楚客户端是否收到了自己回复的 ACK 报文所以服务端每收到一个 SYN 就只能先主动建立一个连接如果客户端发送的 SYN 报文在网络中阻塞了重复发送多次 SYN 报文那么服务端在收到请求后就会建立多个冗余的无效链接造成不必要的资源浪费。TCP 三次握手客户端第三次发送的确认包丢失了发生什么当第三次握手丢失了如果服务端那一方迟迟收不到这个确认报文就会触发超时重传机制重传 SYN-ACK 报文直到收到第三次握手或者达到最大重传次数就断开连接。注意ACK 报文是不会有重传的当 ACK 丢失了就由对方重传对应的报文。就是说第三次握手不会重传只有第二次握手会一直重传服务端发送第二个报文后连接的状态进入什么状态syn_rcvd 状态三次握手和 accept 是什么关系 accept 做了哪些事情tcp 完成三次握手后连接会被保存到内核的全连接队列调用 accpet 就是从把连接取出来给用户程序使用。客户端发送的第一个 SYN 报文服务器没有收到怎么办在这之后如果客户端迟迟收不到服务端的 SYN-ACK 报文第二次握手就会触发「超时重传」机制重传 SYN 报文而且重传的 SYN 报文的序列号都是一样的。通常第一次超时重传是在 1 秒后第二次超时重传是在 2 秒第三次超时重传是在 4 秒后第四次超时重传是在 8 秒后第五次是在超时重传 16 秒后。没错每次超时的时间是上一次的 2 倍。如果超过了最大重传次数还是没有收到服务端的 SYN-ACK 报文,就断开连接。服务器收到第一个 SYN 报文回复的 SYN ACK 报文丢失了怎么办因此当第二次握手丢失了客户端和服务端都会重传客户端会重传 SYN 报文也就是第一次握手最大重传次数由 tcp_syn_retries内核参数决定服务端会重传 SYN-ACK 报文也就是第二次握手最大重传次数由 tcp_synack_retries 内核参数决定。客户端重传超过最大次数后会断开客户端的连接。服务端重传超过最大次数后会断开服务端的连接。假设客户端重传了 SYN 报文服务端这边又收到重复的 SYN 报文怎么办会继续发送第二次握手报文。第一次握手客户端发送SYN报后服务端回复ACK报那这个过程中服务端内部做了哪些工作服务端收到客户端发起的 SYN 请求后内核会把该连接存储到半连接队列并向客户端响应 SYNACK接着客户端会返回 ACK服务端收到第三次握手的 ACK 后内核会把连接从半连接队列移除创建一个全连接放到全连接队列并将其添加到 accept 中等待进程调用 accept 函数时把连接取出来。不管是半连接队列还是全连接队列都有最大长度限制超过限制时内核会直接丢弃或返回 RST 包。大量SYN包发送给服务端服务端会发生什么事情会导致TCP 半连接队列打满这样当 TCP 半连接队列满了后续再在收到 SYN 报文就会丢弃导致客户端无法和服务端建立连接。避免 SYN 攻击方式可以有以下四种方法• 调大 netdev_max_backlog增大网卡接收数据包的最大值• 增大 TCP 半连接队列• 开启 tcp_syncookies• 减少 SYNACK 重传次数就是减少第二次握手重试的次数开启 tcp_syncookies当 「 SYN 队列」满之后后续服务端收到 SYN 包不会丢弃而是根据算法计算出一个 cookie值• 将 cookie 值放到第二次握手报文的「序列号」里然后服务端回第二次握手给客户端• 服务端接收到客户端的应答报文时服务端会检查这个 ACK 包的合法性。如果合法将该连接对象放入到「 Accept 队列」。• 最后应用程序通过调用 accpet() 接口从「 Accept 队列」取出的连接。TCP 四次挥手过程说一下具体过程•客户端主动调用关闭连接的函数于是就会发送 FIN 报文这个 FIN 报文代表客户端不会再发送数据了进入 FIN_WAIT_1 状态•服务端收到了 FIN 报文然后马上回复一个 ACK 确认报文此时服务端进入 CLOSE_WAIT 状态。在收到 FIN 报文的时候TCP 往接收缓冲区末尾插入 EOFEOF之前的数据都是没处理完的• 接着当服务端在 read 数据的时候最后自然就会读到 EOF接着 read() 就会返回 0这时服务端应用程序如果有数据要发送的话就发完数据后才调用关闭连接的函数如果服务端应用程序没有数据要发送的话可以直接调用关闭连接的函数这时服务端就会发一个 FIN 包这个 FIN 报文代表服务端不会再发送数据了之后处于 LAST_ACK 状态•客户端接收到服务端的 FIN 包并发送 ACK 确认包给服务端此时客户端将进入 TIME_WAIT 状态• 服务端收到 ACK 确认包后就进入了最后的CLOSE 状态• 客户端经过 2MSL 时间之后也进入CLOSE 状态为什么4次挥手中间两次不能变成一次服务器收到客户端的 FIN 报文时内核会马上回一个 ACK 应答报文但是服务端应用程序可能还有数据要发送所以并不能马上发送 FIN 报文而是将发送 FIN 报文的控制权交给服务端应用程序• 如果服务端应用程序有数据要发送的话就发完数据后才调用关闭连接的函数• 如果服务端应用程序没有数据要发送的话可以直接调用关闭连接的函数第二次和第三次挥手能合并嘛服务端「没有数据要发送」并且「开启了 TCP 延迟确认机制」那么第二和第三次挥手就会合并传输这样就出现了三次挥手。第三次挥手一直没发会发生什么如果连接是用shutdown 函数关闭的连接可以一直处于 FIN_WAIT2 状态因为它可能还可以接收数据。但对于close 函数关闭的孤儿连接由于无法再发送和接收数据所以这个状态不可以持续太久而 tcp_fin_timeout 控制了这个状态下连接的持续时长默认值是 60 秒超时后连接就会直接关闭。第二次和第三次挥手之间主动断开的那端能干什么如果主动断开的一方是调用了 shutdown 函数来关闭连接并且只选择了关闭发送能力且没有关闭接收能力的话那么主动断开的一方在第二次和第三次挥手之间还可以接收数据。断开连接时客户端 FIN 包丢失服务端的状态是什么如果第一次挥手丢失了那么客户端迟迟收不到被动方的 ACK 的话也就会触发超时重传机制重传 FIN 报文重发次数由 tcp_orphan_retries 参数控制,超过最大次数后会断开连接。当客户端重传 FIN 报文的次数超过 tcp_orphan_retries 后就不再发送 FIN 报文则会在等待一段时间时间为上一次超时时间的 2 倍如果还是没能收到第二次挥手那么客户端直接进入到 close 状态而服务端还是ESTABLISHED状态为什么四次挥手之后要等2MSL?TTL 的值一般是 64Linux 将 MSL 设置为 30 秒意味着 Linux 认为数据报文经过 64 个路由器的时间不会超过 30 秒如果超过了就认为报文已经消失在网络中了。TIME_WAIT 等待 2 倍的 MSL比较合理的解释是 网络中可能存在来自发送方的数据包当这些发送方的数据包被接收方处理后又会向对方发送响应所以一来一回需要等待 2 倍的时间。比如如果被动关闭方没有收到断开连接的最后的 ACK 报文就会触发超时重发 FIN 报文另一方接收到 FIN 后会重发 ACK 给被动关闭方 一来一去正好 2 个 MSL。可以看到 2MSL时长 这其实是相当于至少允许报文丢失一次。比如若 ACK 在一个 MSL 内丢失这样被动方重发的 FIN 会在第 2 个 MSL 内到达TIME_WAIT 状态的连接可以应对。兜底迟滞报文等待网络中残留的旧 TCP 报文彻底消亡防止新连接建立后收到旧连接的过期报文保障四次挥手最后 ACK 可靠送达若最后一次 ACK 报文丢失被动关闭方会超时重传 FIN2MSL 刚好覆盖「FIN 重传 ACK 再次回复」一来一回的全网传输时长服务端出现大量的timewait有哪些原因?第一个场景HTTP 没有使用长连接第二个场景HTTP 长连接超时第三个场景HTTP 长连接的请求数量达到上限HTTP 没有使用长连接只要任意一方的 HTTP header 中有 Connection:close 信息就无法使用 HTTP 长连接机制这样在完成一次 HTTP 请求/处理后就会关闭连接。根据大多数 Web 服务的实现不管哪一方禁用了 HTTP Keep-Alive都是由服务端主动关闭连接那么此时服务端上就会出现 TIME_WAIT 状态的连接。HTTP 长连接超时如果现象是有大量的客户端建立完 TCP 连接后很长一段时间没有发送数据那么大概率就是因为 HTTP 长连接超时导致服务端主动关闭连接产生大量处于 TIME_WAIT 状态的连接。HTTP 长连接的请求数量达到上限比如 nginx 的 keepalive_requests 这个参数这个参数是指一个 HTTP 长连接建立之后nginx 就会为这个连接设置一个计数器记录这个 HTTP 长连接上已经接收并处理的客户端请求的数量。如果达到这个参数设置的最大值时则 nginx 会主动关闭这个长连接那么此时服务端上就会出现 TIME_WAIT 状态的连接。TCP和UDP区别是什么连接TCP 是面向连接的传输层协议传输数据前先要建立连接UDP 是不需要连接即刻传输数据。• 服务对象TCP 是一对一的两点服务即一条连接只有两个端点。UDP 支持一对一、一对多、多对多的交互通信• 可靠性TCP 是可靠交付数据的数据可以无差错、不丢失、不重复、按序到达。UDP 是不可靠的传输协议不保证可靠交付数据发送的数据丢了就丢了不会有任何措施。但是我们可以基于 UDP 传输协议实现一个可靠的传输协议比如 QUIC 协议• 拥塞控制、流量控制TCP 有拥塞控制和流量控制机制保证数据传输的安全性。UDP 则没有即使网络非常拥堵了也不会影响 UDP 的发送速率。• 首部开销TCP 首部长度较长会有一定的开销首部在没有使用「选项」字段时是 20 个字节如果使用了「选项」字段则会变长的。UDP 首部只有 8 个字节并且是固定不变的开销较小。• 传输方式TCP 是流式传输没有边界但保证顺序和可靠。UDP 是一个包一个包的发送是有边界的但可能会丢包和乱序。TCP为什么可靠传输连接管理即三次握手和四次挥手。连接管理机制能够建立起可靠的连接这是保证传输可靠性的前提。• 序列号TCP将每个字节的数据都进行了编号这就是序列号。序列号的具体作用如下能够保证可靠性既能防止数据丢失又能避免数据重复。能够保证有序性按照序列号顺序进行数据包还原。能够提高效率基于序列号可实现多次发送一次确认。• 确认应答接收方接收数据之后会回传ACK报文报文中带有此次确认的序列号用于告知发送方此次接收数据的情况。在指定时间后若发送端仍未收到确认应答就会启动超时重传。• 超时重传超时重传主要有两种场景数据包丢失在指定时间后若发送端仍未收到确认应答就会启动超时重传向接收端重新发送数据包。确认包丢失当接收端收到重复数据(通过序列号进行识别)时将其丢弃并重新回传ACK报文。• 流量控制接收端处理数据的速度是有限的如果发送方发送数据的速度过快就会导致接收端的缓冲区溢出进而导致丢包。为了避免上述情况的发生TCP支持根据接收端的处理能力来决定发送端的发送速度。这就是流量控制。流量控制是通过在TCP报文段首部维护一个滑动窗口来实现的。• 拥塞控制拥塞控制就是当网络拥堵严重时发送端减少数据发送。拥塞控制是通过发送端维护一个拥塞窗口来实现的。可以得出发送端的发送速度受限于滑动窗口和拥塞窗口中的最小值。拥塞控制方法分为慢开始拥塞避免、快重传和快恢复。怎么用udp实现httpUDP 是不可靠传输的但基于 UDP 的 QUIC 协议 可以实现类似 TCP 的可靠性传输在http3 就用了 quic 协议。• 连接迁移QUIC支持在网络变化时快速迁移连接例如从WiFi切换到移动数据网络以保持连接的可靠性。• 重传机制QUIC使用重传机制来确保丢失的数据包能够被重新发送从而提高数据传输的可靠性。• 前向纠错QUIC可以使用前向纠错技术在接收端修复部分丢失的数据降低重传的需求提高可靠性和传输效率。• 拥塞控制QUIC内置了拥塞控制机制可以根据网络状况动态调整数据传输速率以避免网络拥塞和丢包提高可靠性。tcp粘包怎么解决
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2553724.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!