一、概述
传输控制协议(英语:Transmission Control Protocol,缩写为 TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能,用户数据包协议(UDP)是同一层内另一个重要的传输协议。
在因特网协议族(Internet protocol suite)中,TCP层是位于IP层之上,应用层之下的中间层。不同主机的应用层之间经常需要可靠的、像管道一样的连接,但是IP层不提供这样的流机制,而是提供不可靠的包交换。
应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,然后TCP把数据流分区成适当长度的报文段(通常受该计算机连接的网络的数据链路层的最大传输单元(MTU)的限制)。之后TCP把结果包传给IP层,由它来通过网络将包传送给接收端实体的TCP层。TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。
数据在TCP层称为Stream,数据分组称为分段(Segment)。作为比较,数据在IP层称为Datagram,数据分组称为分片(Fragment)。 UDP 中分组称为Message。
数据帧(Frame):是一种信息单位,它的起始点和目的点都是数据链路层。
数据包(Packet):也是一种信息单位,它的起始和目的地是网络层。
数据报(Datagram):通常是指起始点和目的地都使用无连接网络服务的的网络层的信息单元。
段(Segment):通常是指起始点和目的地都是传输层的信息单元。
数据链路层的PDU叫做Frame(帧);
网络层的PDU叫做Packet(数据包);
TCP的叫做Segment(数据段);
二、TCP整体,三次握手,四次挥手
2.1、tcp/ip整体概述
通过上图可以看到
2.2、TCP数据包结构
偏移 | 位0–3 | 4–7 | 8–15 | 16–31 | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 来源连接端口 | 目的连接端口 | ||||||||||||||||||||||||||||||
32 | 序列号码【seq】 | |||||||||||||||||||||||||||||||
64 | 确认号码【ack】 | |||||||||||||||||||||||||||||||
96 | 报头长度 | 保留 | 标志符 | 窗口大小 | ||||||||||||||||||||||||||||
128 | 校验和 | 紧急指针 | ||||||||||||||||||||||||||||||
160 | 选项字段 | |||||||||||||||||||||||||||||||
160/192+ | 数据 |
2.3、详细概述
来源连接端口(16位长)-辨识发送连接端口
目的连接端口(16位长)-辨识接收连接端口
序列号(seq,32位长)
如果含有同步化旗标(SYN),则此为最初的序列号;第一个数据比特的序列码为本序列号加一。
如果没有同步化旗标(SYN),则此为第一个数据比特的序列码。
确认号(ack,32位长)—期望收到的数据的开始序列号。也即已经收到的数据的字节长度加1。
报头长度(4位长)—以4字节为单位计算出的数据段开始地址的偏移值。
保留—须置0
标志符
URG—为1表示高优先级数据包,紧急指针字段有效。
ACK—为1表示确认号字段有效
PSH—为1表示是带有PUSH标志的数据,指示接收方应该尽快将这个报文段交给应用层而不用等待缓冲区装满。
RST—为1表示出现严重差错。可能需要重现创建TCP连接。还可以用于拒绝非法的报文段和拒绝连接请求。
SYN—为1表示这是连接请求或是连接接受请求,用于创建连接和使顺序号同步
FIN—为1表示发送方没有数据要传输了,要求释放连接。
窗口(WIN,16位长)—表示从确认号开始,本报文的接受方可以接收的字节数,即接收窗口大小。用于流量控制。
校验和(Checksum,16位长)—对整个的TCP报文段,包括TCP头部和TCP数据,以16位字进行计算所得。这是一个强制性的字段。
紧急指针(16位长)—本报文段中的紧急数据的最后一个字节的序号。
选项字段—最多40字节。每个选项的开始是1字节的kind字段,说明选项的类型。
0:选项表结束(1字节)
1:无操作(1字节)用于选项字段之间的字边界对齐。
2:最大报文段长度(4字节,Maximum Segment Size,MSS)通常在创建连接而设置SYN标志的数据包中指明这个选项,指明本端所能接收的最大长度的报文段。通常将MSS设置为(MTU-40)字节,携带TCP报文段的IP数据报的长度就不会超过MTU,从而避免本机发生IP分片。只能出现在同步报文段中,否则将被忽略。
3:窗口扩大因子(4字节,wscale),取值0-14。用来把TCP的窗口的值左移的位数,使窗口值乘倍。只能出现在同步报文段中,否则将被忽略。这是因为现在的TCP接收数据缓冲区(接收窗口)的长度通常大于65535字节。
4:sackOK—发送端支持并同意使用SACK选项。
5:SACK实际工作的选项。
8:时间戳(10字节,TCP Timestamps Option,TSopt)
发送端的时间戳(Timestamp Value field,TSval,4字节)
时间戳回显应答(Timestamp Echo Reply field,TSecr,4字节)
填充: 这是为了使整个首部长度是 4 字节的整数倍
其他选项:
窗口扩大: 占 3 字节,其中有一个字节表示移位值 S.新的窗口值等于TCP 首部中的窗口位数增大到(16 + S),相当于把窗口值向左移动 S 位后获得实际的窗口大小
时间戳: 占10 字节,其中最主要的字段时间戳值字段(4字节)和时间戳回送回答字段(4字节)
选择确认: 接收方收到了和前面的字节流不连续的两2字节.如果这些字节的序号都在接收窗口之内,那么接收方就先收下这些数据,但要把这些信息准确地告诉发送方,使发送方不要再重复发送这些已收到的数据
2.4、三个阶段
2.4.1、链接建立【三次握手】
图解
过程:
1》c-s:客户端A 的 TCP 向服务端 B 发出连接请求报文段,其首部中的同步位 SYN = 1,并选择序号 seq = x,表明传送数据时的第一个数据字节的序号是 x
客户端进入SYN_SEND状态,等待服务器的确认;
2》s-c:服务端B 的 TCP 收到连接请求报文段后,如同意,则发回确认(服务端B 在确认报文段中应使 SYN = 1,使 ACK = 1,其确认号ack = x﹢1,自己选择的序号 seq = y)
服务器进入SYN_RECV状态;
3》c-s:客户端A 收到此报文段后向 服务端B 给出确认,其 ACK = 1,确认号 ack = y﹢1(客户端A 的 TCP 通知上层应用进程,连接已经建立,服务端B 的 TCP 收到客户端主机 A 的确认后,也通知其上层应用进程:TCP 连接已经建立)
客户端和服务器端都进入ESTABLISHED状态
至此完成三次握手,可以进入下一阶段
2.4.2、数据传送
2.4.3、连接释放【四次挥手】
图解:
步骤:
tcp四次挥手,由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。
由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
1》客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送(报文段4)(A 把连接释放报文段首部的 FIN = 1,其序号seq = u,等待 B 的确认)
主机A进入FIN_WAIT_1状态;这表示主机A没有数据要发送给主机B了;
2》B 发出确认,确认号 ack = u+1,而这个报文段自己的序号 seq = v(TCP 服务器进程通知高层应用进程.从 A 到 B 这个方向的连接就释放了,TCP 连接处于半关闭状态.B 若发送数据,A 仍要接收)
主机A进入FIN_WAIT_2状态;主机B告诉主机A,我也没有数据要发送了,可以进行关闭连接了;
3》主机B向主机A发送FIN报文段,请求关闭连接,同时主机B进入CLOSE_WAIT状态;若 B 已经没有要向 A 发送的数据,其应用进程就通知 TCP 释放连接
4》A 收到连接释放报文段后,必须发出确认,在确认报文段中 ACK = 1,确认号 ack=w﹢1,自己的序号 seq = u + 1
TCP采用四次挥手关闭连接如图所示为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?
这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。
更多扩展:https://www.cnblogs.com/yueminghai/p/6646043.html
原文地址:https://www.cnblogs.com/bjlhx/p/8873138.html