TCP/IP协议,握手,挥手
TCP协议详解 - 王先生架构 - 博客园TCP的三次握手与四次挥手理解及面试题很全面 - 李卓航 - 博客园为什么需要三次握手和四次挥手_白小狮的博客-CSDN博客_为什么要三次挥手Wireshark的window size value和calculated window size_weixin_34051201的博客-CSDN博客(489条消息) TCP异常终止reset报文_craftsman2020的博客-CSDN博客_tcp通信reset(489条消息) TCP的RESET报文_weixin_888988的博客-CSDN博客_tcp reset报文(552条消息) IP协议详解_刘贝斯的博客-CSDN博客_fragment offset调用tcp_send_active_reset发送RESET报文当TCP调用tcp_close时如果socket的sk_receive_queue中skb还有数据的话则调用tcp_send_active_reset向对端发送RESET报文。调用tcp_v4_send_reset发送RESET报文TCP11种状态 - 走看看 (zoukankan.com)旁路阻断技术tcp reset - 积硅步007 - 博客园 (cnblogs.com)(489条消息) 模拟reset包阻断tcp_传智院的博客-CSDN博客_reset包(489条消息) TCP复位报文的发送_redwingz的博客-CSDN博客_tcp复位(503条消息) RFC793中文版_randomain的博客-CSDN博客_rfc793(503条消息) Linux内核的TCP源码入门(一)_lic721的博客-CSDN博客_linux tcp源码(504条消息) 网络包几种格式ethhdr、ether_header、iphdr、tcphdr、udphdr_繁星逸夜的博客-CSDN博客_ether头(608条消息) 【ABC】Tcp抓包以及tcp状态解释_tcp retransmission tcp port numbers reused_菲菲夜的博客-CSDN博客(642条消息) tcp三次握手后被马上rst_【TCP协议】(2)TCP三次握手和四次挥手_weixin_39830323的博客-CSDN博客二、TCP数据的传输过程建立连接后两台主机就可以相互传输数据了。 如下图所示1)主机A初始seq为1200,滑动窗体为100,向主机B传递数据的过程。 2)假设主机B在完全成功接收数据的基础上,那么主机B为了确认这一点向主机A发送 ACK 包并将 Ack 号设置为 1301。 因此按如下的公式确认 Ack 号 Ack号 Seq号 传递的字节数 1 (这是在完全接受成功的情况下) 3)主机A获得B传来的ack(1301)后,开始发送seq为1301,滑动窗体为100的数据。...... 与三次握手协议相同最后加 1 是为了告诉对方要传递的 Seq 号。 上面说了主机B完全成功接收A发来的数据才是这样的,如果存在丢包该如何。 下面分析传输过程中数据包丢失的情况如下图所示上图表示通过 Seq 1301 数据包向主机B传递100字节的数据但中间发生了错误主机B未收到。 经过一段时间后主机A仍未收到对于 Seq 1301 的ACK确认因此尝试重传数据。 为了完成数据包的重传TCP套接字每次发送数据包时都会启动定时器如果在一定时间内没有收到目标机器传回的 ACK 包那么定时器超时数据包会重传。上面也只是一种可能,比如数据1250丢失,那么Ack返回的就是1250,这里面滑动窗口有说明。三、TCP的四次挥手第一次挥手TCP发送一个FIN(结束)用来关闭客户到服务端的连接。客户端进程发出连接释放报文并且停止发送数据。释放数据报文首部FIN1其序列号为sequ(等于前面已经传送过来的数据的最后一个字节的序号加1)此时客户端进入FIN-WAIT-1(终止等待1)状态。TCP规定FIN报文段即使不携带数据也要消耗一个序号。挥手服务端收到这个FIN他发回一个ACK(确认)确认收到序号为收到序号1和SYN一样一个FIN将占用一个序号。服务器收到连接释放报文发出确认报文ACK1acku1并且带上自己的序列号seqv此时服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程客户端向服务器的方向就释放了这时候处于半关闭状态即客户端已经没有数据要发送了但是服务器若发送数据客户端依然要接受。这个状态还要持续一段时间也就是整个CLOSE-WAIT状态持续的时间。客户端收到服务器的确认请求后此时客户端就进入FIN-WAIT-2(终止等待2)状态等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。挥手服务端发送一个FIN(结束)到客户端服务端关闭客户端的连接。服务器将最后的数据发送完毕后就向客户端发送连接释放报文FIN1acku1由于在半关闭状态服务器很可能又发送了一些数据假定此时的序列号为seqw此时服务器就进入了LAST-ACK(最后确认)状态等待客户端的确认。挥手客户端发送ACK(确认)报文确认并将确认的序号1这样关闭完成。客户端收到服务器的连接释放报文后必须发出确认ACK1ackw1而自己的序列号是sequ1此时客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放必须经过2∗∗MSL(最长报文段寿命)的时间后当客户端撤销相应的TCB后才进入CLOSED状态。服务器只要收到了客户端发出的确认立即进入CLOSED状态。同样撤销TCB后就结束了这次的TCP连接。可以看到服务器结束TCP连接的时间要比客户端早一些。思考那么为什么是4次挥手呢为了确保数据能够完成传输。关闭连接时当收到对方的FIN报文通知时它仅仅表示对方没有数据发送给你了但未必你所有的数据都全部发送给对方了所以你可以未必会马上会关闭SOCKET。也即你可能还需要发送一些数据给对方之后再发送FIN报文给对方来表示你同意现在可以关闭连接了所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。可能有人会有疑问tcp我握手的时候为何ACK(确认)和SYN(建立连接)是一起发送。挥手的时候为什么是分开的时候发送呢因为当Server端收到Client端的SYN连接请求报文后可以直接发送SYNACK报文。其中ACK报文是用来应答的SYN报文是用来同步的。但是关闭连接时当Server端收到FIN报文时很可能并不会立即关闭 SOCKET所以只能先回复一个ACK报文告诉Client端你发的FIN报文我收到了。只有等到我Server端所有的报文都发送完了我才能发送FIN报文因此不能一起发送。故需要四步挥手。思考:客户端突然挂掉了怎么办————————————————版权声明本文为CSDN博主「weixin_39830323」的原创文章遵循CC 4.0 BY-SA版权协议转载请附上原文出处链接及本声明。原文链接https://blog.csdn.net/weixin_39830323/article/details/111363030最后发送rst不影响可以不管。rst是为了更快速的断开连接关闭端口。(642条消息) TCP标志位 RST作用、原理、攻击_tcp rst_深山猿的博客-CSDN博客(642条消息) tcp out of order是怎么回事_网络编程TCP协议浅析_weixin_39980234的博客-CSDN博客(642条消息) TCP乱序队列Out-Of-Order_redwingz的博客-CSDN博客(642条消息) Wireshark TS | 服务器在三次握手后发送RST _三次握手rst_7ACE的博客-CSDN博客struct iphdr { #if defined(__LITTLE_ENDIAN_BITFIELD) //小端模式下 __u8 ihl:4,//首部长度(4位) version:4;//ip协议版本IPv4 #elif defined (__BIG_ENDIAN_BITFIELD) //大端模式下 __u8 version:4, ihl:4; #else #error Please fix asm/byteorder.h #endif __u8 tos;//服务类型字段(8位) __be16 tot_len;//16位IP数据报总长度 __be16 id;//16位标识字段唯一表示主机发送的每一分数据报 __be16 frag_off;//(3位分段标志13位分段偏移数) __u8 ttl;//8位数据报生存时间 __u8 protocol;//协议字段8位 __be16 check;//16位首部校验 __be32 saddr; //源IP地址 __be32 daddr; //目的IP地址 };2.TCP首部-固定部分struct tcphdr { __be16 source; // 源端口号,16bit,最大65535 __be16 dest; // 目的端口号,16bit,最大65535 __be32 seq; // 序列号,32bit,表示的是每个字节的序列号,正常发送时会递增,重传时seq值不变 __be32 ack_seq; // 确认号,32bit,下方的ack1时生效,表示的是期望对方下一个报文段的第一个字节的序列号,同时也表示了该序列号之前的字节都已收到 #if defined(__LITTLE_ENDIAN_BITFIELD) __u16 res1:4, doff:4, fin:1, syn:1, rst:1, psh:1, ack:1, urg:1, ece:1, cwr:1; #elif defined(__BIG_ENDIAN_BITFIELD) __u16 doff:4, // 首部长度,4bit,原意是数据偏移量data offset,实际表示的是TCP的首部长度 res1:4, // 保留位, 4bit, 初版的TCP,保留位是6bit cwr:1, // 拥塞窗口减小标志,1表示已设置,0表示未设置. // 1bit,congestion window reduced flag, // 和下方的ece一起使用,表示它接收到了设置ece标志的数据段,它进入了拥塞控制阶段(拥塞窗口在减小). ece:1, // 显示拥塞通知,1表示已设置,0表示未设置. // 1bit,当收到的数据段中,下方的syn1(握手),表示TCP对端支持ECN;当下方的syn-0,表明接收到的TCP包的IP头部的ECN被设置为11,对端已经拥塞了 urg:1, // 紧急标志位,1表示已设置,0表示未设置.1bit,表示下方的urg_ptr生效,需要紧急处理 ack:1, // 确认标志位,1表示已设置,0表示未设置.1bit,表示上方的ack_seq生效 psh:1, // 推送标志位,1表示已设置,0表示未设置.1bit,表示缓存数据要直接向上交付 rst:1, // 重置标志位,1表示已设置,0表示未设置.1bit,表示连接重置 syn:1, // 同步标志位,1表示已设置,0表示未设置.1bit,表示发起连接或者接受连接 fin:1; // 终止标志位,1表示已设置,0表示未设置.1bit,表示最后的数据已发送完,可以终止连接了. #else #error Adjust your asm/byteorder.h defines #endif __be16 window; // 窗口,16bit,表示允许对方发送的字节大小 __sum16 check; // 校验和,16bit,接收方校验数据是否有改动 __be16 urg_ptr; // 紧急数据指针,16bit,上方的urg设置时生效,表示在本报文段中的紧急数据的最后一个字节的偏移量 };为什么会有TCP/IP协议在世界上各地各种各样的电脑运行着各自不同的操作系统为大家服务这些电脑在表达同一种信息的时候所使用的方法是千差万别。就好像圣经中上帝打乱了各地人的口音让他们无法合作一样。计算机使用者意识到计算机只是单兵作战并不会发挥太大的作用。只有把它们联合起来电脑才会发挥出它最大的潜力。于是人们就想方设法的用电线把电脑连接到了一起。但是简单的连到一起是远远不够的就好像语言不同的两个人互相见了面完全不能交流信息。因而他们需要定义一些共通的东西来进行交流TCP/IP就是为此而生。TCP/IP不是一个协议而是一个协议族的统称。里面包括了IP协议IMCP协议TCP协议以及我们更加熟悉的http、ftp、pop3协议等等。电脑有了这些就好像学会了外语一样就可以和其他的计算机终端做自由的交流了。TCP/IP协议分层TCP/IP协议族按照层次由上到下层层包装。应用层:向用户提供一组常用的应用程序比如电子邮件、文件传输访问、远程登录等。远程登录TELNET使用TELNET协议提供在网络其它主机上注册的接口。TELNET会话提供了基于字符的虚拟终端。文件传输访问FTP使用FTP协议来提供网络内机器间的文件拷贝功能。传输层:提供应用程序间的通信。其功能包括一、格式化信息流二、提供可靠传输。为实现后者传输层协议规定接收端必须发回确认并且假如分组丢失必须重新发送。网络层负责相邻计算机之间的通信。其功能包括三方面。一、处理来自传输层的分组发送请求收到请求后将分组装入IP数据报填充报头选择去往信宿机的路径然后将数据报发往适当的网络接口。二、处理输入数据报首先检查其合法性然后进行寻径--假如该数据报已到达信宿机则去掉报头将剩下部分交给适当的传输协议假如该数据报尚未到达信宿则转发该数据报。三、处理路径、流控、拥塞等问题。网络接口层这是TCP/IP软件的最低层负责接收IP数据报并通过网络发送之或者从网络上接收物理帧抽出IP数据报交给IP层。IP 是无连接的IP 用于计算机之间的通信。IP 是无连接的通信协议。它不会占用两个正在通信的计算机之间的通信线路。这样IP 就降低了对网络线路的需求。每条线可以同时满足许多不同的计算机之间的通信需要。通过 IP消息或者其他数据被分割为小的独立的包并通过因特网在计算机之间传送。IP 负责将每个包路由至它的目的地。IP地址每个计算机必须有一个 IP 地址才能够连入因特网。每个 IP 包必须有一个地址才能够发送到另一台计算机。网络上每一个节点都必须有一个独立的Internet地址也叫做IP地址。现在通常使用的IP地址是一个32bit的数字也就是我们常说的IPv4标准这32bit的数字分成四组也就是常见的255.255.255.255的样式。IPv4标准上地址被分为五类我们常用的是B类地址。具体的分类请参考其他文档。需要注意的是IP地址是网络号主机号的组合这非常重要。CP/IP 使用 32 个比特来编址。一个计算机字节是 8 比特。所以 TCP/IP 使用了 4 个字节。一个计算机字节可以包含 256 个不同的值00000000、00000001、00000010、00000011、00000100、00000101、00000110、00000111、00001000 ....... 直到 11111111。现在你知道了为什么 TCP/IP 地址是介于 0 到 255 之间的 4 个数字。TCP 使用固定的连接TCP 用于应用程序之间的通信。当应用程序希望通过 TCP 与另一个应用程序通信时它会发送一个通信请求。这个请求必须被送到一个确切的地址。在双方“握手”之后TCP 将在两个应用程序之间建立一个全双工 (full-duplex) 的通信。这个全双工的通信将占用两个计算机之间的通信线路直到它被一方或双方关闭为止。UDP 和 TCP 很相似但是更简单同时可靠性低于 TCP。IP 路由器当一个 IP 包从一台计算机被发送它会到达一个 IP 路由器。IP 路由器负责将这个包路由至它的目的地直接地或者通过其他的路由器。在一个相同的通信中一个包所经由的路径可能会和其他的包不同。而路由器负责根据通信量、网络中的错误或者其他参数来进行正确地寻址。域名12 个阿拉伯数字很难记忆。使用一个名称更容易。用于 TCP/IP 地址的名字被称为域名。w3school.com.cn 就是一个域名。当你键入一个像 http://www.w3school.com.cn 这样的域名域名会被一种 DNS 程序翻译为数字。在全世界数量庞大的 DNS 服务器被连入因特网。DNS 服务器负责将域名翻译为 TCP/IP 地址同时负责使用新的域名信息更新彼此的系统。当一个新的域名连同其 TCP/IP 地址一同注册后全世界的 DNS 服务器都会对此信息进行更新。TCP/IPTCP/IP 意味着 TCP 和 IP 在一起协同工作。TCP 负责应用软件比如你的浏览器和网络软件之间的通信。IP 负责计算机之间的通信。TCP 负责将数据分割并装入 IP 包然后在它们到达的时候重新组合它们。IP 负责将包发送至接受者。TCP报文格式TCP报文格式1.jpg16位源端口号16位的源端口中包含初始化通信的端口。源端口和源IP地址的作用是标识报文的返回地址。16位目的端口号16位的目的端口域定义传输的目的。这个端口指明报文接收计算机上的应用程序地址接口。32位序号32位的序列号由接收端计算机使用重新分段的报文成最初形式。当SYN出现序列码实际上是初始序列码Initial Sequence NumberISN而第一个数据字节是ISN1。这个序列号序列码可用来补偿传输中的不一致。32位确认序号32位的序列号由接收端计算机使用重组分段的报文成最初形式。如果设置了ACK控制位这个值表示一个准备接收的包的序列码。4位首部长度4位包括TCP头大小指示何处数据开始。保留6位6位值域这些位必须是0。为了将来定义新的用途而保留。标志6位标志域。表示为紧急标志、有意义的应答标志、推、重置连接标志、同步序列号标志、完成发送数据标志。按照顺序排列是URG、ACK、PSH、RST、SYN、FIN。16位窗口大小用来表示想收到的每个TCP数据段的大小。TCP的流量控制由连接的每一端通过声明的窗口大小来提供。窗口大小为字节数起始于确认序号字段指明的值这个值是接收端正期望接收的字节。窗口大小是一个16字节字段因而窗口大小最大为65535字节。16位校验和16位TCP头。源机器基于数据内容计算一个数值收信息机要与源机器数值 结果完全一样从而证明数据的有效性。检验和覆盖了整个的TCP报文段这是一个强制性的字段一定是由发送端计算和存储并由接收端进行验证的。16位紧急指针指向后面是优先数据的字节在URG标志设置了时才有效。如果URG标志没有被设置紧急域作为填充。加快处理标示为紧急的数据段。选项长度不定但长度必须为1个字节。如果没有选项就表示这个1字节的域等于0。数据该TCP协议包负载的数据。在上述字段中6位标志域的各个选项功能如下。URG紧急标志。紧急标志为1表明该位有效。ACK确认标志。表明确认编号栏有效。大多数情况下该标志位是置位的。TCP报头内的确认编号栏内包含的确认编号w1为下一个预期的序列编号同时提示远端系统已经成功接收所有数据。PSH推标志。该标志置位时接收端不将该数据进行队列处理而是尽可能快地将数据转由应用处理。在处理Telnet或rlogin等交互模式的连接时该标志总是置位的。RST复位标志。用于复位相应的TCP连接。SYN同步标志。表明同步序列编号栏有效。该标志仅在三次握手建立TCP连接时有效。它提示TCP连接的服务端检查序列编号该序列编号为TCP连接初始端一般是客户端的初始序列编号。在这里可以把TCP序列编号看作是一个范围从0到4294967295的32位计数器。通过TCP连接交换的数据中每一个字节都经过序列编号。在TCP报头中的序列编号栏包括了TCP分段中第一个字节的序列编号。FIN结束标志。TCP三次握手所谓三次握手Three-Way Handshake即建立TCP连接就是指建立一个TCP连接时需要客户端和服务端总共发送3个包以确认连接的建立。在socket编程中这一过程由客户端执行connect来触发整个流程如下图所示TCP三次握手.png1第一次握手Client将标志位SYN置为1随机产生一个值seqJ并将该数据包发送给ServerClient进入SYN_SENT状态等待Server确认。2第二次握手Server收到数据包后由标志位SYN1知道Client请求建立连接Server将标志位SYN和ACK都置为1ackJ1随机产生一个值seqK并将该数据包发送给Client以确认连接请求Server进入SYN_RCVD状态。3第三次握手Client收到确认后检查ack是否为J1ACK是否为1如果正确则将标志位ACK置为1ackK1并将该数据包发送给ServerServer检查ack是否为K1ACK是否为1如果正确则连接建立成功Client和Server进入ESTABLISHED状态完成三次握手随后Client与Server之间可以开始传输数据了。简单来说就是1、建立连接时客户端发送SYN包SYNi到服务器并进入到SYN-SEND状态等待服务器确认2、服务器收到SYN包必须确认客户的SYNacki1,同时自己也发送一个SYN包SYNk,即SYNACK包此时服务器进入SYN-RECV状态3、客户端收到服务器的SYNACK包向服务器发送确认报ACKackk1,此包发送完毕客户端和服务器进入ESTABLISHED状态完成三次握手客户端与服务器开始传送数据。SYN攻击在三次握手过程中Server发送SYN-ACK之后收到Client的ACK之前的TCP连接称为半连接half-open connect此时Server处于SYN_RCVD状态当收到ACK后Server转入ESTABLISHED状态。SYN攻击就是Client在短时间内伪造大量不存在的IP地址并向Server不断地发送SYN包Server回复确认包并等待Client的确认由于源地址是不存在的因此Server需要不断重发直至超时这些伪造的SYN包将产时间占用未连接队列导致正常的SYN请求因为队列满而被丢弃从而引起网络堵塞甚至系统瘫痪。SYN攻击时一种典型的DDOS攻击检测SYN攻击的方式非常简单即当Server上有大量半连接状态且源IP地址是随机的则可以断定遭到SYN攻击了使用如下命令可以让之现行#netstat -nap | grep SYN_RECVTCP四次挥手所谓四次挥手Four-Way Wavehand即终止TCP连接就是指断开一个TCP连接时需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中这一过程由客户端或服务端任一方执行close来触发整个流程如下图所示TCP四次挥手.png由于TCP连接时全双工的因此每个方向都必须要单独进行关闭这一原则是当一方完成数据发送任务后发送一个FIN来终止这一方向的连接收到一个FIN只是意味着这一方向上没有数据流动了即不会再收到数据了但是在这个TCP连接上仍然能够发送数据直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭而另一方则执行被动关闭上图描述的即是如此。1第一次挥手Client发送一个FIN用来关闭Client到Server的数据传送Client进入FIN_WAIT_1状态。2第二次挥手Server收到FIN后发送一个ACK给Client确认序号为收到序号1与SYN相同一个FIN占用一个序号Server进入CLOSE_WAIT状态。3第三次挥手Server发送一个FIN用来关闭Server到Client的数据传送Server进入LAST_ACK状态。4第四次挥手Client收到FIN后Client进入TIME_WAIT状态接着发送一个ACK给Server确认序号为收到序号1Server进入CLOSED状态完成四次挥手。为什么建立连接是三次握手而关闭连接却是四次挥手呢这是因为服务端在LISTEN状态下收到建立连接请求的SYN报文后把ACK和SYN放在一个报文里发送给客户端。而关闭连接时当收到对方的FIN报文时仅仅表示对方不再发送数据了但是还能接收数据己方也未必全部数据都发送给对方了所以己方可以立即close也可以发送一些数据给对方后再发送FIN报文给对方来表示同意现在关闭连接因此己方ACK和FIN一般都会分开发送。为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态原因有二一、保证TCP协议的全双工连接能够可靠关闭二、保证这次连接的重复数据段从网络中消失先说第一点如果Client直接CLOSED了那么由于IP协议的不可靠性或者是其它网络原因导致Server没有收到Client最后回复的ACK。那么Server就会在超时之后继续发送FIN此时由于Client已经CLOSED了就找不到与重发的FIN对应的连接最后Server就会收到RST而不是ACKServer就会以为是连接错误把问题报告给高层。这样的情况虽然不会造成数据丢失但是却导致TCP协议不符合可靠连接的要求。所以Client不是直接进入CLOSED而是要保持TIME_WAIT当再次收到FIN的时候能够保证对方收到ACK最后正确的关闭连接。再说第二点如果Client直接CLOSED然后又再向Server发起一个新连接我们不能保证这个新连接与刚关闭的连接的端口号是不同的。也就是说有可能新连接和老连接的端口号是相同的。一般来说不会发生什么问题但是还是有特殊情况出现假设新连接和已经关闭的老连接端口号是一样的如果前一次连接的某些数据仍然滞留在网络中这些延迟数据在建立新连接之后才到达Server由于新连接和老连接的端口号是一样的又因为TCP协议判断不同连接的依据是socket pair于是TCP协议就认为那个延迟的数据是属于新连接的这样就和真正的新连接的数据包发生混淆了。所以TCP连接还要在TIME_WAIT状态等待2倍MSL这样可以保证本次连接的所有数据都从网络中消失。作者RaphetS 链接https://www.jianshu.com/p/ef892323e68f 來源简书 著作权归作者所有。商业转载请联系作者获得授权非商业转载TCP11种状态 - 走看看 (zoukankan.com)也就是说当两端都主动发送FIN的时候并且在收到对方对自己发送的FIN之前收到了对方发送的FIN的时候两边就都进入了CLOSING状态这个在状态图上显示的很清楚。这个用俗话说就是”同时关闭“。时序图我就不给出了请自行搜索或者自己画。关于TCP的CLOSING状态和CLOSE_WAIT状态浅析 - 知乎 (zhihu.com)CLOSE_WAIT一般多久CLOSE_WAIT 没有像 TIME_WAIT常见约 60s那种内核固定超时时长完全取决于本端应用何时 close()• 正常对端 FIN 后应用读到 EOF 立刻关通常是 毫秒几秒• 异常应用不关、卡死、FD 泄漏可到 分钟小时甚至更久直到进程退出所以本单这几分钟属于偏长更像本端应用迟迟没关 socket而不是协议“正常等一会儿”。