了解最新公司动态及行业资讯
它就像是网络世界中的一套通用语言和规则,让不同的计算机和网络设备能够相互理解和交流。
TCP(Transmission Control Protocol,传输控制协议)主要负责确保数据的可靠传输。比如说,当您在网上发送一封电子邮件时,TCP 会确保这封邮件的每一部分都能准确无误地到达目的地,并且按照正确的顺序进行重组。如果有部分数据丢失或损坏,TCP 会要求重新发送这些数据,以保证信息的完整性。
IP(Internet Protocol,网际协议)则主要负责给网络中的设备分配地址,并确定数据传输的路径。就好像是给每个参与通信的设备都赋予了一个“门牌号”,同时规划出了数据从发送方到接收方的“路线图”。
举个例子,您在网上购物时,您的订单信息通过 TCP 保证准确可靠地传输,而 IP 则负责将这些信息沿着正确的网络路径发送到商家的服务器。
再比如,您在线观看视频时,TCP 确保视频数据的连贯性和完整性,IP 则负责把这些数据从视频服务器准确地传送到您的设备上。
总之,TCP/IP 协议是现代网络通信的基石,使得全球范围内的计算机和网络能够高效、稳定地进行数据交换和通信。
三次握手过程
假设客户端向服务器发起 TCP 连接。
第一次握手:客户端的 TCP 程序首先向服务器的 TCP 程序发送一个 TCP 报文。这个报文不包含数据,且它的 SYN 标志位被置为 1,表示这是一条建立连接的 TCP 报文段,因此这个报文段也被称为 SYN 报文段。客户端的 TCP 程序随机选择一个序号作为客户端报文的初始序号(假设为 client_isn),放入这个报文段的序号部分。这个报文段由运输层传递到网络层后,被封装在一个 IP 数据报中发往服务器。第二次握手:包含 SYN 报文段的 IP 数据报被服务器接收,服务器的网络层将 SYN 数据报抽取出来,交给运输层,同时服务器为该 TCP 连接分配资源(包括发送缓存、接收缓存和变量等),并向客户端发送允许连接的 TCP 报文段。这条允许连接的报文段不包含数据,SYN 标志位也被置为 1,同时它的 ACK 标志位也被置为 1,表示它是 SYN 报文段的确认报文,所以这条允许连接的报文段也被称为 SYNACK 报文段。服务器随机选择一个序号,作为服务器报文段的初始序号(假设称为 server_isn),并将其放入 SYNACK 报文段的序号部分,同时确认号字段被设置为 client_isn + 1(SYN 报文段的序号+1)。这个报文段可以解释为服务器向客户端说:“我收到了你的连接请求,我允许你连接,我的初始序号是 server_isn”。第三次握手:当客户端接收到 SYNACK 报文段后,它也将为 TCP 连接分配资源(缓存和变量),同时生成一条 SYNACK 报文段的确认报文,并发送给服务器。由于经过上面两个步骤,已经算是建立了连接,所以这次的 SYN 标志位将被置为 0,而不是 1(ACK 标志位是 1)。同时,这条报文段的序号被设置为 client_isn + 1(第一条客户报文的序号是 client_isn,而这是它的下一条,所以+1),而确认序号被设置为 server_isn + 1(第一条服务器报文的序号是 server_isn,客户端成功接收,所以期望服务器下一次发送 server_isn + 1)。和上面两条报文不同,第三条报文可以携带数据,比如 HTTP 的请求就是在 TCP 的第三次握手报文中发送到服务器的。三次握手的原因
首先,两次握手是必要的,第一次握手客户端发送 SYN 报文到服务器,服务器接收到后可确认客户端到服务器是可达的;服务器向客户端发送响应的 SYNACK 报文,客户端接收到后可确认服务器到客户端也是可达的。而第三次握手的作用在于客户端向服务器确认已收到其初始序号,完成同步,确保可以开始相互传输数据。若没有第三次握手,服务器将无法保证客户端接收到了自己的 SYNACK 报文段,若此时 SYNACK 报文段丢失,客户端不知道服务器的初始序号,将无法处理之后到达客户端的数据。
四次挥手过程
数据传输完毕后,客户端和服务器都可以主动发起关闭连接的请求,这里假设客户端主动关闭。
第一次挥手:客户端发送一个 FIN 报文段,FIN 标志位被置为 1,表示这是一条断开连接的报文段,用来通知服务器客户端已经没有数据要发送了,但此时客户端仍可以接收服务器发来的数据。第二次挥手:服务器收到 FIN 报文段后,知道客户端想要断开连接,就发送一个 ACK 报文段作为确认,确认号为收到的 FIN 报文段的序号加 1,此时服务器进入 CLOSE_WAIT 状态。这个状态表示服务器已经收到客户端的关闭请求,但可能还有一些数据尚未发送完毕。第三次挥手:服务器处理完剩余的数据后,向客户端发送一个 FIN 报文段,FIN 标志位同样被置为 1,表明服务器也没有数据要发送了,此时服务器进入 LAST_ACK 状态,等待客户端的最后确认。第四次挥手:客户端收到服务器的 FIN 报文段后,再发送一个 ACK 报文段给服务器,确认号为收到的 FIN 报文段的序号加 1,此时客户端进入 TIME_WAIT 状态。服务器收到客户端的 ACK 报文段后,连接正式关闭。客户端在 TIME_WAIT 状态等待一段时间(通常为 2 倍的报文最大生存时间,即 2MSL)后,也关闭连接。四次挥手的原因
TCP 连接是全双工的,即双方都可以同时进行数据的发送和接收。在断开连接时,双方都需要分别确认自己和对方是否还有数据要发送,四次挥手正好可以在双方之间同步这两个问题。通过四次挥手,可以确保双方都能安全、可靠地关闭连接,释放相关资源。如果缺少其中某个步骤,可能会导致连接处于假死状态,连接占用的资源无法被释放。
在四次挥手中,TIME_WAIT 状态的作用主要有两个。一是确保最后一个 ACK 报文段能够被服务器正确接收,如果这个 ACK 报文段丢失,服务器会超时重传 FIN 报文段,客户端在 TIME_WAIT 状态下能够再次收到并重传 ACK 报文段;二是防止已失效的连接请求报文段出现在后续的新连接中,经过 2MSL 的时间后,可以保证在本次连接中产生的所有报文段都从网络中消失。
想象一下你要和朋友打电话的过程,这可以帮助你理解 TCP/IP 的建立过程。
首先,你知道朋友的电话号码(这就相当于网络中的 IP 地址)。
然后你拿起电话拨打这个号码(这类似于客户端向服务器发送 SYN 码,请求建立连接)。
当你的朋友听到电话铃声并接起电话时(这相当于服务器收到客户端发来的请求,并发送 SYN+ACK 表示可以连接),他会说:“喂,你好!”(这就是服务器发送的确认信号)。
接着你听到他的回应后,也会说:“你好!”(这相当于客户端收到服务器的确认后,再次向服务器发送 ACK 码表示确认)。
至此,你们之间的通话连接就建立成功了(这意味着 TCP 连接建立完成,双方可以开始进行数据通信了)。
在这个例子中:
“你拨打号码”就是 TCP 建立连接过程中的第一次握手。“朋友接起电话并回应”是第二次握手。“你听到回应后再次说话”则是第三次握手。通过这样的三次“握手”,就可以确保你和朋友都知道对方已经准备好进行通话,从而建立起可靠的连接,接下来就可以愉快地交流啦。类似地,在网络通信中,TCP/IP 通过三次握手建立连接后,客户端和服务器就可以进行数据的传输了。
需要注意的是,这只是一个通俗易懂的例子,实际的 TCP/IP 协议要复杂得多,但这个例子可以帮助你初步理解其建立连接的基本过程。在实际的网络通信中,还涉及到更多的细节和机制,以确保数据的可靠传输、流量控制、拥塞控制等。
假设采用两次握手建立连接。如果客户端第一次发送的连接请求报文在网络中滞留了,客户端超时未收到响应会重新发送连接请求并成功建立连接,完成数据传输后关闭连接。而此时,之前滞留的那个第一次的连接请求报文突然到达了服务端,服务端会误以为是客户端又发起了新的连接请求,于是向客户端发送确认报文并分配资源等待客户端的数据。但客户端并不会响应,这就造成了服务端资源的浪费。
同步双方的初始序列号三次握手可以让双方都能明确对方的初始序列号,从而保证后续数据传输的有序性和正确性。如果只有两次握手,客户端能知道服务端的初始序列号,但服务端无法确认客户端的初始序列号。
确保双方都具备收发数据的能力第一次握手,客户端向服务端表明自己有发送能力;第二次握手,服务端回应客户端,表明服务端有接收和发送能力;第三次握手,客户端回应服务端,表明客户端有接收能力。通过三次握手,双方都能确认彼此具备收发数据的能力。
例如,想象一个场景:客户端发送了连接请求,但由于网络延迟,服务端没有及时收到。客户端超时后重新发送请求并成功建立连接。如果是两次握手,当延迟的第一次请求到达服务端时,服务端会认为这是新的连接请求并建立连接,导致错误。
又如,若只有两次握手,客户端无法确认服务端是否能正确接收自己的确认信息,也就无法保证双方能按照正确的序列号进行数据传输。
综上所述,三次握手是为了保证 TCP 连接建立的可靠性和准确性,避免资源浪费和数据传输错误。
客户端
一开始,客户端处于 `CLOSED`(关闭)状态。客户端发送 SYN 报文后,进入 `SYN_SENT`(已发送 SYN 报文)状态。客户端收到服务器的 SYN + ACK 报文后,进入 `ESTABLISHED`(已建立连接)状态,此时客户端可以开始发送和接收数据。服务器
最初,服务器处于 `LISTEN`(监听)状态,等待客户端的连接请求。当服务器收到客户端的 SYN 报文后,进入 `SYN_RCVD`(已收到 SYN 报文)状态,并向客户端发送 SYN + ACK 报文。服务器收到客户端的 ACK 报文后,也进入 `ESTABLISHED`(已建立连接)状态,此时服务器也可以开始发送和接收数据。例如,假设一个网站服务器正在等待用户的访问请求(处于 `LISTEN` 状态)。当用户在浏览器中输入网址并发起连接请求时(客户端发送 SYN 报文),服务器就会从 `LISTEN` 状态转变为 `SYN_RCVD` 状态。随后,服务器向客户端发送响应(SYN + ACK 报文),并等待客户端的最后确认。一旦收到客户端的确认(ACK 报文),服务器就与客户端成功建立连接,都进入 `ESTABLISHED` 状态,从而可以进行数据的传输,比如网页内容的发送和用户请求的接收。
再比如,一个在线游戏的客户端想要连接游戏服务器,在发起第一次握手后,客户端就处于 `SYN_SENT` 状态等待服务器的回应。服务器收到请求并做出响应后,客户端再给出最终确认,双方就都能进入 `ESTABLISHED` 状态,开始游戏数据的交互。
SYN_SENT 状态卡住
代表含义:客户端发送 SYN 报文后长时间未收到服务器的响应。可能原因:网络故障,如丢包、延迟过高。服务器负载过高,无法及时处理连接请求。防火墙或安全策略阻止了连接请求。解决方法:检查网络连接,排查网络设备、线路等问题。优化服务器性能,增加资源或优化应用程序。检查防火墙和安全策略设置,确保允许相关连接。SYN_RCVD 状态卡住
代表含义:服务器收到客户端的 SYN 报文并发送 SYN + ACK 后,长时间未收到客户端的 ACK 确认。可能原因:客户端的响应报文丢失。客户端故障或异常。解决方法:检查网络是否存在丢包。确认客户端的状态和配置是否正常。ESTABLISHED 状态未达成
代表含义:三次握手未能成功完成,连接未建立。可能原因:上述提到的任何导致前两个状态卡住的原因持续存在。双方的 TCP 实现不兼容。解决方法:全面排查网络、服务器、客户端的问题。检查和更新双方的 TCP 协议实现或相关软件。例如,在一个企业网络中,如果发现客户端在 SYN_SENT 状态卡住,网络管理员首先会使用 Ping 命令检查网络连通性,确定是否存在网络丢包。如果网络正常,会进一步查看服务器的资源使用情况,看是否存在负载过高的问题。
又如,在一个分布式系统中,如果多个客户端与服务器连接时在 SYN_RCVD 状态卡住,可能需要检查服务器的防火墙规则,看是否误阻止了客户端的响应报文。
在 TCP 连接建立过程中,TIME_WAIT 状态是主动关闭连接的一方在收到被动关闭方的 FIN 包后并返回 ACK 后进入的状态。这个状态会持续一段时间,通常称为 2MSL(Maximum Segment Lifetime,报文最大生存时间的两倍)。
TIME_WAIT 状态存在的原因主要有以下两点:
实现 TCP 全双工连接的可靠终止:网络是不可靠的,在四次挥手关闭 TCP 连接的过程中,最后一个 ACK 包是由主动关闭连接的一端发出的。这个 ACK 有可能在路上丢失,使得处于 LAST_ACK 状态的一端(通常是服务器端)接收不到。如果接收不到,服务器就会超时重传 FIN 请求。所以主动关闭的一方需要处在 TIME_WAIT 状态并等待 2MSL 时间来处理服务器重传的 FIN 请求,以确保服务器能够正常关闭。如果主动关闭方在发送最后一个 ACK 后立即释放连接资源,当重传的 FIN 到达时,由于找不到对应的连接信息,可能会导致错误。允许旧的重复报文分组在网络中消逝:网络的不可靠性意味着 TCP 报文可能会延迟到达。在 TIME_WAIT 状态时,两端的端口不能立即使用,要等到 2MSL 时间结束后才可以继续使用。在等待期间,任何迟到的报文都将被丢弃,这样可以避免延迟到达的 TCP 报文被误认为是新 TCP 连接的数据,防止这些延迟报文对新连接造成数据错乱。MSL 是任何 IP 数据报能够在因特网中存活的最长时间,具体的时间长度由 TCP 的实现和系统设置决定。一般来说,MSL 在实际使用中通常是 30 秒或 1 分钟。
如果在高并发场景中存在大量短连接,可能会导致出现大量的 TIME_WAIT 状态连接,从而占用系统资源。为了解决这个问题,可以采取一些优化措施,例如修改系统设置缩短 TIME_WAIT 时长、使用长连接、设置套接字选项(如 SO_REUSEADDR)等。
在 Linux 系统中,可以通过一些内核参数来进行优化,例如将`net.ipv4.tcp_tw_reuse`设置为 1 允许客户端在 TIME_WAIT 状态重用端口(需同时打开 TCP 头部时间戳选项`net.ipv4.tcp_timestamps`且开启后收到最后一个包后超过 1 秒);将`net.ipv4.tcp_tw_recycle`设置为 1 快速回收 TIME_WAIT 状态的套接字,但需注意该参数在经过 NAT 或负载均衡后可能会出现问题。另外,还可以调整`
/proc/sys/net/ipv4/tcp_fin_timeout`的值来缩减 MSL,但这可能会导致延迟报文无法清除以及主动关闭连接一端不能收到重传来的 FIN 请求,影响很多基于 TCP 的应用的连接复用和调优,因此在实际生产环境中需要谨慎操作。要查看系统中处于 TIME_WAIT 状态的 TCP 连接数量,可以使用类似`netstat -tan | grep time_wait`的命令(具体命令可能因操作系统而略有不同)。同时,也可以通过统计 TCP 各种状态的连接数来全面了解 TCP 连接的情况,例如使用`netstat -n | awk /^tcp/{++s($nf)} END{for(i in s) print i,s(i)}`命令。
例如,对于一个高并发的 Web 服务,如果发现由于短连接导致大量的 TIME_WAIT 状态,首先可以尝试开启 `net.ipv4.tcp_tw_reuse` 参数来复用端口。同时,优化应用逻辑,尽量使用长连接来与后端服务通信,减少连接的频繁创建和关闭。
再比如,对于一个分布式系统,如果某个服务器节点因为 TIME_WAIT 状态导致资源紧张,可以通过负载均衡将流量分发到其他节点,减轻该节点的压力。
例如,在一个在线游戏的服务器端,如果在玩家登录高峰期发现大量玩家连接建立时间过长,同时服务器的 CPU 使用率飙升,网络延迟也增加,那么很可能存在 TCP 连接建立的性能问题。
再比如,对于一个电商网站,如果在促销活动期间新用户注册时连接建立失败率显著上升,就需要对连接建立过程进行性能排查。
例如,在一个高并发的 Web 服务器场景中,可以通过使用负载均衡设备来优化网络路径,减少 RTT。同时,对服务器的资源分配进行预配置,使得新连接能够快速获取所需资源。对于频繁访问的客户端,利用缓存记住其连接信息,下次连接时能够快速响应。
又如,在移动网络环境中,由于网络不稳定导致 RTT 波动较大,可以通过调整 TCP 协议的超时重传时间来适应这种情况,避免不必要的连接延迟。
例如,一家大型电商网站在促销活动前,根据历史流量数据预估并发连接数,提前调整服务器内核的 TCP 缓冲区大小,并增加负载均衡器后端的服务器实例数量,同时对服务器应用程序进行性能优化和压力测试,确保在活动期间能够快速处理大量的 TCP 连接建立请求,提供流畅的用户体验。
又如,一家金融交易公司为了应对高频交易时的大量 TCP 连接,升级了服务器的网络接口卡,并采用异步 I/O 模型处理连接请求,大大提高了连接建立的性能和系统的整体响应速度。
例如,对于一个高并发的电商网站,启用 TFO 可以让用户在点击商品页面时更快地加载出内容。同时,优化服务器的内核参数,结合 CDN 部署,能够显著提升用户在购物过程中的连接建立速度和页面加载速度,提供更好的用户体验。
又如,在一个企业内部的数据库应用中,使用连接池技术可以大大减少每次数据库操作时建立 TCP 连接的时间,提高系统的整体性能。
长连接是指在建立连接后,保持连接状态,通信双方可以在一段时间内持续进行数据传输,直到一方主动关闭连接。
短连接则是每次通信完成后立即关闭连接,下次通信时再重新建立连接。
长连接的优点
减少连接建立和关闭的开销:因为不需要频繁地进行三次握手和四次挥手的过程,节省了时间和资源。适用于频繁交互的场景:例如实时通信、在线游戏等,能够提供更流畅的通信体验。保持连接状态,便于实现推送等功能。长连接的缺点
占用系统资源:长时间保持连接会占用一定的服务器资源,如内存等。可能导致连接失效:如果网络出现异常,长连接可能会在不知不觉中失效,而客户端和服务器可能无法及时感知。短连接的优点
释放资源及时:每次通信结束后立即释放连接相关的资源,对服务器资源的占用较少。适合不频繁的通信:例如网页浏览中获取单个页面的情况。短连接的缺点
连接建立和关闭开销大:对于频繁的小数据量通信,这种开销会累积,影响性能。不适合实时性要求高的场景:每次通信都要重新建立连接,可能导致数据传输的延迟。例如,在一个即时通讯应用中,通常会采用长连接,使得用户之间能够实时收发消息。而对于一个简单的静态网页浏览,每次请求页面都使用短连接,因为用户在不同页面之间的访问间隔通常较长,不需要一直保持连接。
又如,在一个物联网系统中,设备向服务器上报数据,如果数据上报较为频繁且实时性要求高,适合用长连接;但如果设备只是偶尔上报数据,短连接可能更节省资源。
长连接的典型场景
即时通讯应用:如微信、QQ 等,需要实时推送消息,保持用户之间的通信不间断。在线游戏:玩家在游戏过程中需要持续与服务器进行数据交互,以实现实时的动作同步和状态更新。监控系统:传感器或监控设备需要不断向服务器发送数据,以便及时发现异常情况。股票交易系统:实时获取股票价格变化和交易信息,对数据的及时性要求很高。短连接的典型场景
普通网页浏览:用户访问网页时,每次请求一个页面就建立连接,获取完数据后关闭连接,因为用户在不同页面之间的访问通常不是连续的。一次性数据查询:例如查询一次天气信息、航班时刻表等,查询完成后就不再需要保持连接。图片验证码获取:用户请求获取验证码图片,获取成功后即可关闭连接。简单的 API 调用:对于一些不频繁且数据量较小的 API 调用,如获取某个产品的简要信息。例如,在股票交易系统中,使用长连接可以让投资者实时看到股票价格的波动和交易的执行情况,不会因为频繁建立和关闭连接而错过关键的交易时机。
而在普通的电商网站上,用户浏览商品页面时,每次点击新的页面都是短连接,因为用户在不同页面之间的停留和操作是不确定的,短连接可以更有效地利用服务器资源。