TCP 概述 可靠的、面向连接的、基于字节流、全双工的协议

目标

  • 了解 TCP 协议
  • 了解三次握手

一、TCP 是面向连接的协议

  • 面向连接(connection-oriented)
    面向连接的协议要求正式发送数据之前需要通过握手建立一个逻辑连接,结束通信时也是通过有序的四次挥手来断开连接
  • 无连接(connectionless)
    无连接的协议则不需要在发送数据前建立连接

三次握手

通过三次握手,协商好双方后续通信的起始***、窗口缩放大小等信息
TCP 概述 可靠的、面向连接的、基于字节流、全双工的协议

第一次握手:客户端将标志位 SYN 置为 1,并随机产生一个值 seq = x,然后将该数据包发送给服务端,客户端进入 SYN_SENT 状态,等待服务端确认
第二次握手:服务端收到客户端发来的数据包,看到标志位 SYN = 1,从而知道客户端想要建立连接,于是服务端将标志位 ACK 置为 1(标志位 SYN 此时还是 1),设置 ack = x + 1随机产生一个值 seq = y,然后将该数据包发送给客户端以确认连接请求,服务端进入 SYN_RECVD 状态,客户端进入 ESTABLISHED 状态
第三次握手:客户端收到确认数据包后,检查 ack 是否为 x + 1,标志位 ACK 是否为 1,如果都满足,则将标志位 ACK 置为 1,设置 ack = y + 1,然后将该数据包发送给服务端,服务端检查 ack 是否为 y + 1,标志位 ACK 是否为 1,如果都满足,则连接建立成功。服务端进入 ESTABLISHED 状态

标记位
紧急位 URG:紧急处理,可提升数据包发送的优先级
确认位 ACK:代表确认号是否有效
急迫位 PSH:接收方应尽快将这个报文交给应用层
重置位 PST:将建立的连接重置
同步位 SYN:同步序号用来发起一个连接
终止位 FIN:终止一个连接

查看三次握手的标记位
TCP 概述 可靠的、面向连接的、基于字节流、全双工的协议

第一次握手,标记位 SYN = 1,表示请求
TCP 概述 可靠的、面向连接的、基于字节流、全双工的协议

第二次握手,标记位 SYN = 1、ACK = 1,表示应答
TCP 概述 可靠的、面向连接的、基于字节流、全双工的协议

第三次握手,标记位 ACK = 1,表示确认
TCP 概述 可靠的、面向连接的、基于字节流、全双工的协议

二、TCP 协议是可靠的

IP 是一种无连接、不可靠的协议,尽最大可能将数据报从发送者传输给接收者,但并不保证到达的顺序会与它们被传输的顺序一致,也不保证是否重复、是否到达

TCP 在 IP 层基础上,构建可起靠的传输层协议,可靠需要有机制来保障,措施如下:

  • 对每个包提供校验和
  • 包的***解决了接收数据的乱序、重复问题
  • 超时重传
  • 流量控制、拥塞控制
    TCP 概述 可靠的、面向连接的、基于字节流、全双工的协议

校验和

如果收到一个校验和有差错的报文,TCP 会直接丢弃不回复,等待发送端重新发送该报文
TCP 包的首部中用两个字节来表示校验和

包的***

每个包都有唯一的***,TCP 根据***对收到的网络包进行排序,然后把结果传递给上层应用程序
TCP 收到重复数据(超时重传导致),根据包序号丢弃重复的数据

超时重传

TCP 发送数据后,会启动一个定时器,等待对端确认收到这个数据包。在指定时间内没有收到 ACK 确认,则会重传该数据包,然后继续等待更长时间,如果还没有收到 ACK 确认再重传,经过多次重传还不行后,TCP 会放弃这个网络包

流量控制、拥塞控制

三、TCP 是面向字节流的协议

流的特点就是没有边界

调用 Socket 库中的程序组件 write(<描述符>, <发送的数据>, <数据长度>) 函数发送数据,只是把数据拷贝到了内核缓冲区,至于何时发送出去、分几次发送完毕是不确定的

举个栗子:调用 write 函数发送 500、800 字节数据
TCP 概述 可靠的、面向连接的、基于字节流、全双工的协议

具体的字节发送情况决定因素包含:路径最大传输单元 MTU、发送窗口大小、拥塞窗口大小等

四、TCP 是全双工的协议

在 TCP 中,发送端和接收端可以是客户端/服务端,也可以是服务端/客户端
在任意时刻,通信双方既可以发送数据也可以接收数据,每个方向的数据流都有独立的***、滑动窗口大小、MSS 等信息

五、问题

Q:TCP 提供了字节流服务,而通信双方不保留记录的边界,应用程序如何提供自定义的记录标识?
应用程序使用自己约定的规则来表示消息的边界,比如有一些使用回车+换行("\r\n"),比如 Redis 的通信协议(RESP protocol)