TCP的简介:
TCP:传输控制协议---面向连接的可靠传输协议
在完成传输层的基本工作之上,还需要进一步的保障传输的可靠性
面向连接:通过TCP的三次握手建立端到端的虚链路
可靠传输:4种可靠机制 --- 确认、重传、排序、流控(滑动窗口)
TCP三次握手建立连接:
所谓三次握手(Three-way Handshake),是指建立一个 TCP 连接时,需要客户端和服务器总共发送3个报文。
三次握手的目的是连接服务器指定端口,建立 TCP 连接,并同步连接双方的序列号和确认号,交换 TCP 窗口大小信息。
- TCP的序号和确认号:
32位序号 seq:Sequence number 缩写seq ,TCP通信过程中某一个传输方向上的字节流的每个字节的序号,通过这个来确认发送的数据有序,比如现在序列号为1000,发送了1000,下一个序列号就是2000。
32位确认号 ack:Acknowledge number 缩写ack,TCP对上一次seq序号做出的确认号,用来响应TCP报文段,给收到的TCP报文段的序号seq加1。 - TCP的标志位
每个TCP段都有一个目的,这是借助于TCP标志位选项来确定的,允许发送方或接收方指定哪些标志应该被使用,以便段被另一端正确处理。
用的最广泛的标志是 SYN,ACK 和 FIN,用于建立连接,确认成功的段传输,最后终止连接。
- SYN:简写为
S
,同步标志位,用于建立会话连接,同步序列号;- ACK: 简写为
.
,确认标志位,对已接收的数据包进行确认;- FIN: 简写为
F
,完成标志位,表示我已经没有数据要发送了,即将关闭连接;
三次握手过程的示意图如下:
- 第一次握手:
客户端将TCP报文标志位SYN置为1,随机产生一个序号值seq=J,保存在TCP首部的序列号(Sequence Number)字段里,指明客户端打算连接的服务器的端口,并将该数据包发送给服务器端,发送完毕后,客户端进入SYN_SENT
状态,等待服务器端确认。 - 第二次握手:
服务器端收到数据包后由标志位SYN=1知道客户端请求建立连接,服务器端将TCP报文标志位SYN和ACK都置为1,ack=J+1,随机产生一个序号值seq=K,并将该数据包发送给客户端以确认连接请求,服务器端进入SYN_RCVD
状态。 - 第三次握手:
客户端收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给服务器端,服务器端检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,客户端和服务器端进入ESTABLISHED
状态,完成三次握手,随后客户端与服务器端之间可以开始传输数据了。
注意:我们上面写的ack和ACK,不是同一个概念:
- 小写的ack代表的是头部的确认号Acknowledge number, 缩写ack,是对上一个包的序号进行确认的号,ack=seq+1。
- 大写的ACK,则是我们上面说的TCP首部的标志位,用于标志的TCP包是否对上一个包进行了确认操作,如果确认了,则把ACK标志位设置成1。
TCP 三次握手跟现实生活中的人与人打电话是很类似的:
三次握手:
“喂,你听得到吗?”
“我听得到呀,你听得到我吗?”
“我能听到你,今天 ……“
经过三次的互相确认,大家就会认为对方对听的到自己说话,并且愿意下一步沟通,否则,对话就不一定能正常下去了。
【1】为什么不能用两次握手进行连接?
3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。
现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机Server和Client之间的通信,假定Client给Server发送一个连接请求分组,Server收到了这个分组,并发送了确认应答分组。按照两次握手的协定,Server认为连接已经成功地建立了,可以开始发送数据分组。可是,Client在Server的应答分组在传输中被丢失的情况下,将不知道Server是否已准备好,不知道Server建立什么样的序列号,Client甚至怀疑Server是否收到自己的连接请求分组。在这种情况下,Client认为连接还未建立成功,将忽略Server发来的任何数据分 组,只等待连接确认应答分组。而Server在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。