TCP报⽂解析
TCP是⼀种可靠的、⾯向连接的字节流服务。源主机在传送数据前需要先和⽬标主机建⽴连接。然后,在此连接上,被编号的数据段按序收发。同时,要求对每个数据段进⾏确认,保证了可靠性。如果在指定的时间内没有收到⽬标主机对所发数据段的确认,源主机将再次发送该数据段。
TCP(Transmission Control Protocol 传输控制协议)是⼀种⾯向连接的、可靠的、基于字节流的传输层通信协议。当应⽤层向TCP层发送⽤于⽹间传输的、⽤8位字节表⽰的数据流,TCP则把数据流分割成适当长度的报⽂段,最⼤传输段⼤⼩(MSS)通常受该计算机连接的⽹络的数据链路层的最⼤传送单元(MTU)限制。之后TCP把数据包传给IP层,由它来通过⽹络将包传送给接收端实体的TCP层。
最⼤报⽂段长度MSS(Maximum Segment Size)
指明⾃⼰期望对⽅发送TCP报⽂段时那个数据字段的长度。⽐如:1460字节。数据字段的长度加上TCP⾸部的长度才等于整个TCP报⽂段的长度。MSS不宜设的太⼤也不宜设的太⼩。若选择太⼩,极端情况下,TCP报⽂段只含有1字节数据,在IP层传输的数据报的开销⾄少有40字节(包括TCP报⽂段的⾸部和IP数据报的⾸部)。这样,⽹络的利⽤率就不会超过1/41。若TCP报⽂段⾮常长,那么在IP层传输时就有可能要分解成多个短数据报⽚。在终点要把收到的各个短数据报⽚装配成原来的TCP报⽂段。当传输出错时还要进⾏重传,这些也都会使开销增⼤。因此MSS应尽可能⼤,只要在IP层传输时不需要再分
⽚就⾏。在连接建⽴过程中,双⽅都把⾃⼰能够⽀持的MSS写⼊这⼀字段。MSS只出现在SYN报⽂中。即:MSS出现在SYN=1的报⽂段中
三年级家长会班主任发言稿MTU和MSS值的关系:MTU=MSS+IP Header+TCPHeader
通信双⽅最终的MSS值=较⼩MTU-IP Header-TCP Headercoldsteel
TCP报头结构
图2-5 TCP头部结构
源、⽬标端⼝号字段:占16⽐特。TCP协议通过使⽤"端⼝"来标识源端和⽬标端的应⽤进程。端⼝号
可以使⽤0到65535之间的任何数字。在收到服务请求时,操作系统动态地为客户端的应⽤程序分配端⼝号。在服务器端,每种服务在"众所周知的端⼝"为⽤户提供服务。源端⼝和IP地址的作⽤是标识报⽂的返回地址。⽬的端⼝指明接收⽅计算机上的应⽤程序接⼝。TCP报头中的源端⼝号和⽬的端⼝号同IP数据报中的源IP与⽬的IP唯⼀确定⼀条TCP连接。
顺序号字段:占32⽐特。⽤来标识从TCP源端向TCP⽬标端发送的数据字节流,它表⽰在这个报⽂段数据部分的第⼀个字节。在TCP传送的流中,每⼀个字节⼀个序号。e.g.⼀个报⽂段的序号为300,此报⽂段数据部分共有100字节,则下⼀个报⽂段的序号为400。所以序号确保了TCP传输的有序性。
确认号字段:占32⽐特。只有ACK标志为1时,确认号字段才有效。它包含⽬标端所期望收到源端的下⼀个数据字节。确认号,即ACK,指明下⼀个期待收到的字节序号,表明该序号之前的所有数据已经正确⽆误的收到。确认号只有当ACK标志为1时才有效,建⽴连接
时,SYN报⽂的ACK标志位为0。
每次发送的序列号是系统随机⽣成的
确认号=序列号+包的⼤⼩,图中只加1是不正确的
如果确认号 < 序列号+包的⼤⼩,需要重传数据包
数据偏移/头部长度字段:占4⽐特。给出头部占32⽐特的数⽬。由于⾸部可能含有可选项内容,因此TCP报头的长度是不确定的。没有任何选项字段的TCP头部长度为20字节;4位⾸部长度字段所能表⽰的最⼤值为1111,转化为10进制为15,15*32/8 = 60,故报头最⼤长度为60字节。⾸部长度也叫数据偏移,是因为⾸部长度实际上指⽰了数据区在报⽂段中的起始偏移值。
phenomenon什么意思保留:占6⽐特,为将来定义新的⽤途保留,现在⼀般置0。
标志位字段:占6⽐特。共6个,每⼀个标志位表⽰⼀个控制功能,各⽐特的含义如下:
URG:紧急指针标志,为1时表⽰紧急指针有效,为0则忽略紧急指针。
ACK:确认序号标志,为1时表⽰确认号有效,为0表⽰报⽂中不含确认信息,忽略确认号字段。
PSH:push标志,为1表⽰是带有push标志的数据,指⽰接收⽅在接收到该报⽂段以后,应尽快将这个报⽂段交给应⽤程序,⽽不是在缓冲区排队。
RST:重置连接标志,⽤于重置由于主机崩溃或其他原因⽽出现错误的连接。或者⽤于拒绝⾮法的报⽂段和拒绝连接请求。
SYN:同步序号,⽤于建⽴⼀个连接过程,在连接请求中,SYN=1和ACK=0表⽰该数据段没有使⽤捎带的确认域,⽽连接应答捎带⼀个确认,即SYN=1和ACK=1。
FIN:finish标志,⽤于释放⼀个连接,为1时表⽰发送⽅已经没有数据发送了,即关闭本⽅数据流。
窗⼝⼤⼩字段:占16⽐特。此字段⽤来进⾏流量控制。单位为字节数,⽤来告知发送端接受端的缓存⼤⼩,以此控制发送端发送数据的速率,从⽽达到流量控制。窗⼝⼤⼩是⼀个16bit字段,因⽽窗⼝⼤⼩最⼤为65535。表⽰从确认号开始,本报⽂的源⽅可以接收的字节数,即源⽅接收窗⼝⼤⼩
TCP校验和字段:占16⽐特。奇偶校验,此校验和是对整个的 TCP 报⽂段,包括 TCP 头部和 TCP 数据,以 16 位字进⾏计算所得。由发送端计算和存储,并由接收端进⾏验证。
紧急指针字段:占16⽐特。只有当 URG 标志置 1 时紧急指针才有效。紧急指针是⼀个正的偏移量,和顺序号字段中的值相加表⽰紧急数据最后⼀个字节的序号。 TCP 的紧急⽅式是发送端向另⼀端发送紧急数据的⼀种⽅式。
可选项字段:占32⽐特。可能包括"窗⼝扩⼤因⼦"、"时间戳"等选项。最常见的可选字段是最长报⽂⼤⼩,⼜称为MSS(Maximum Segment Size),每个连接⽅通常都在通信的第⼀个报⽂段(为建⽴连接⽽设置SYN标志为1的那个段)中指明这个选项,它表⽰本端所能接受的最⼤报⽂段的长度。选项长度不⼀定是32位的整数倍,所以要加填充位,即在这个字段中加⼊额外的零,以保证TCP头是32的整数倍。
数据部分字段: TCP 报⽂段中的数据部分是可选的,不定长度,为上层协议封装好的数据。在⼀个连接建⽴和⼀个连接终⽌时,双⽅交换的报⽂段仅有 TCP ⾸部。如果⼀⽅没有数据要发送,也使⽤没有任何数据的⾸部来确认收到的数据。在处理超时的许多情况中,也会发送不带任何数据的报⽂段。vers
tcp常⽤的option选项:
TCP三次握⼿
TCP怎样才能保证可靠的传输任务,就是通过三次握⼿。通过序列号字段、确认号字段与标志位字段SYN,ACK配合实现
⾸先由Client发出请求连接即 SYN=1 ACK=0 (请看头字段的介绍), TCP规定SYN=1时不能携带数据,但要消耗⼀个序号,因此声明⾃⼰的序号是 q=x
然后 Server 进⾏回复确认,即 SYN=1 ACK=1 q=y, ack=x+1,
再然后 Client 再进⾏⼀次确认,但不⽤SYN 了,这时即为 ACK=1, q=x+1, ack=y+1.
TCP四次挥⼿
通过序列号字段、确认号字段与标志位字段FIN,ACK配合实现
每次发送的序列号是系统随机⽣成的
nurs确认号=序列号+包的⼤⼩,图中只加1是不正确的
如果确认号 < 序列号+包的⼤⼩,需要重传数据包
当客户A 没有东西要发送时就要释放 A 这边的连接,A会发送⼀个报⽂(没有数据),其中 FIN 设置为1, 服务器B收到后会给应⽤程序⼀个信,这时A那边的连接已经关闭,即A不再发送信息(但仍可接收信息)。
A收到B的确认后进⼊等待状态,等待B请求释放连接, B数据发送完成后就向A请求连接释放,也是⽤FIN=1 表⽰, 并且⽤ ack =
u+1(如图),A收到后回复⼀个确认信息,并进⼊ TIME_WAIT 状态, 等待 2MSL 时间。
为什么要等待呢?
全新版大学英语听说教程2答案
为了这种情况: B向A发送 FIN = 1 的释放连接请求,但这个报⽂丢失了, A没有接到不会发送确认信息, B 超时会重传,这时A在
gnnWAIT_TIME 还能够接收到这个请求,这时再回复⼀个确认就⾏了。(A收到 FIN = 1 的请求后 WAIT_TIME会重新记时)
另外服务器B存在⼀个保活状态,即如果A突然故障死机了,那B那边的连接资源什么时候能释放呢? 就是保活时间到了后,B会发送探测信息, 以决定是否释放连接。
注意:中断连接端可以是Client端,也可以是Server端。
来个通俗版的解释:
其实英文
假设Client端发起中断连接请求,也就是发送FIN报⽂。Server端接到FIN报⽂后,意思是说"我Client端没有数据要发给你了",但是如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。所以你先发送ACK,"告诉Client端,你的请求我收到了,但是我还没准备好,请继续你等我的消息"。这个时候Client端就进⼊FIN_WAIT状态,继续等待Server端的FIN报⽂。当Server端确定数据已发送完成,则向Client端发送FIN报⽂,"告诉Client端,好了,我这边数据发完了,准备好关闭连接了"。Client端收到FIN报⽂后,"就知道可以关闭连接了,但是他还是不相信⽹络,怕Server端不知道要关闭,所以发送ACK后进⼊TIME_WAIT状态,如果Server端没有收到ACK则可以重传。“,Server端收到ACK后,"就知道可以断开连接了"。Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。Ok,TCP连接就这样关闭了!(是服务端先关闭,后客户端关闭)
【问题1】为什么连接的时候是三次握⼿,关闭的时候却是四次握⼿?
答:因为当Server端收到Client端的SYN连接请求报⽂后,可以直接发送SYN+ACK报⽂。其中ACK报⽂是⽤来应答的,SYN报⽂是⽤来同步的。但关闭连接时,当Server端收到FIN报⽂时,很可能并不会⽴即关闭SOCKET,所以只能先回复⼀个ACK报⽂,告
诉Client端,"你发的FIN报⽂我收到了"。只有等到我Server端所有的报⽂都发送完了,我才能发送FIN报⽂,因此不能⼀起发送。故需要四步握⼿。冀教版三年级英语上册
【问题2】为什么TIME_WAIT状态需要经过2MSL(最⼤报⽂段⽣存时间)才能返回到CLOSE状态?
答:虽然按道理,四个报⽂都发送完毕,我们可以直接进⼊CLOSE状态了,但是我们必须假象⽹络是不可靠的,有可以最后⼀个ACK丢失。所以TIME_WAIT状态就是⽤来重发可能丢失的ACK报⽂。
nsible整个客户端所经历的状态:
整个服务端经历的状态: