TCP协议
TCP (Transmission Control Protocol) 是面向连接、可靠的传输层协议,数据的传送要先从建立连接开始,TCP为了保证可靠性做了很多控制,比如 为了保证不丢包,每一个包都设置了序列号,接收者在接收到一定数量的连续字节流后才发送确认(选择确认),并且如果包丢失时(没有收到该报对应的ACK),针对跟包重新发送即可。TCP使用 一个 检验和函数来检验数据是否有错,在发送和接收时都会计算校验和等。
TCP连接有许多的标志符号(FLAGS),这里做一个说明
- SYN 表示建立连接
- FIN 表示关闭连接
- ACK (acknowledge) 确认信号,表示响应
- PSH 表示有 DATA 数据传输
RST 表示连接重置
其中,ACK 可能与 SYN,FIN等同时使用,比如 SYN 和 ACK 可能同时为1,它表示的就是建立连接之后的响应,如果只是单一的 SYN ,它表示的只是建立连接。 SYN 和 FIN 不会同时为1,因为前者表示建立连接,而后者表示的是断开连接。RST 一般是在 FIN 之后才会出现为1的情况,表示的是连接重置。
所以,出现 FIN 包或者 RST 包时,便认为 客户端 与 服务端断开连接,而出现 SYN 和 SYN + ACK 包时,认为客户端与服务端建立了一个连接。PSH 为1的情况,一般只出现在 DATA 内容不为0 的包中,也就是说 PSH为 1 表示的是有真正的 TCP 数据包内容被传递。在 TCP 握手的过程中,第一次的 seq number 是随机产生的。
三次握手
TCP 属于传输层协议,这些数据的发送都是可以通过抓包得到的,三次握手意味着有三次TCP数据的传输(2次发送,一次接受),每次的数据包内容(报文格式)都包括上诉符号位的信息,以及 序号(seq)、确认号(ack)等
以下的设置确认号 表示将受到的随机seq的值 加1,作为响应的ACK。ACK起到应答的作用,而SYN起同步作用
- 第一次握手
Client 端发送握手请求报文(标志位 SYN 为1),并随机产生一个seq 值 x,Client 进入 SYN_SENT 状态 等待 Server确认
- 第二次握手
Server 端收到连接请求后,回复 ACK 报文(设置ACK 为1),生成并设置一个随机 seq值 y 及 设置确认号(x+1),并将 SYN 也置为1
- 第三次握手
Client 收到 服务端确认的报文,检查 ack 是否正确,ACK是否为1,如果正确则设置确认号,将数据包发送给服务端,服务端检查 ACK,如果正确则连接简历成功,Client 和 Server 都进入 ESTABLISHED 状态,完成握手,接下来就可以进行数据的传输了。
四次挥手(断开连接)
由于 TCP 连接是全双工的(通信数据在两个方向可以同时传输,可以理解为双行道),所以每个方向都必须单独进行关闭。当一方完成它的数据发送任务后就可以发送一个FIN报文 来终止这个房型的连接。当收到一个 FIN只疑问着这一个方向上没有数据流动了,一个 TCP连接在收到一个FIN后,依然能够发送数据。
- Client 发送一个 FIN报文,用来关闭 客户端到服务端的数据传送
- 服务端收到 FIN 报文,发回一个ACK确认回文。
- 服务端关闭与客户端的连接,发送一个FIN报文给客户端
- 客户端发回ACK确认回文。
为什么关闭连接需要四次挥手(响应的ACK报文和FIN报文分开发送了)
这是因为服务端的 LISTEN 状态收到 SYN报文的建立连接的请求后,它将 ACK 和 SYN放在一个报文立来发送。但是,关闭连接时,当收到对方的 FIN 报文时,它仅仅表示对方没有数据发送给你了;未必所有的数据都已经全部发送给对方了,所以你 不可以马上关闭 SOCKET,也可能你也还需要发送一些数据给对方之后,再发送 FIN 报文来给对方表示你同意现在可以关闭连接了,所以在 断开连接时,ACK报文 和 FIN报文 是分开发送的。