TCP(Transmission Control Protocol,传输控制协议)是 TCP/IP 模型传输层的核心协议,专为可靠、有序、面向连接的端到端数据传输设计,是互联网中绝大多数关键应用(如网页访问、文件传输、邮件收发)的底层支撑
一、TCP 的核心特性
1. 面向连接
TCP 通信前必须先建立端到端的连接(三次握手),通信结束后需释放连接(四次挥手),类似 "打电话"(先拨号接通,再通话,最后挂电话)。
- 连接是全双工的:双方可同时发送和接收数据;
- 连接基于 "四元组" 标识:源 IP、源端口、目的 IP、目的端口(唯一确定一个 TCP 连接)。
2. 可靠传输
TCP 通过一系列机制保证数据无丢失、无重复、按序到达:
- 确认应答(ACK):接收方收到数据后必须向发送方返回确认;
- 超时重传:发送方若超时未收到确认,自动重传数据;
- 差错校验:通过校验和检测数据是否损坏,损坏则丢弃并触发重传;
- 重排乱序包:接收方对乱序到达的数据包重新排序,按序交付给应用层;
- 丢弃重复包:通过序列号识别重复数据并丢弃。
3. 字节流传输
TCP 将应用层数据视为连续的 "字节流",无消息边界(这也是粘包问题的根源),仅保证字节的顺序和完整性,不关心应用层的消息划分。
4. 流量控制
TCP 通过滑动窗口机制控制发送方的传输速率,避免接收方缓冲区溢出(接收方通过窗口大小告知发送方 "最多还能接收多少数据")。
5. 拥塞控制
TCP 通过算法感知网络拥塞(如丢包、延迟增加),动态调整发送速率,避免加剧网络拥堵(核心算法:慢启动、拥塞避免、快速重传、快速恢复)。
二、TCP 的核心工作机制
1. 连接建立:三次握手
目的:同步双方的序列号和确认号,分配资源(如缓冲区),确保双方收发能力正常。
流程:
- SYN:客户端向服务器发送 SYN 报文(同步序列号,初始序列号为 x),请求建立连接;
- SYN+ACK:服务器收到后,回复 SYN+ACK 报文(同步自己的初始序列号 y,确认客户端的 x+1);
- ACK:客户端收到后,回复 ACK 报文(确认服务器的 y+1),连接正式建立。
为什么需要三次握手?
- 防止 "失效的连接请求报文段" 被服务器接收(如客户端发送的 SYN 报文因网络延迟滞留,后续重发并建立连接,滞留的 SYN 后续到达服务器,若两次握手则服务器会建立无效连接,浪费资源);
- 同步双方的序列号(TCP 依赖序列号实现可靠传输)。
2. 数据传输:滑动窗口 + 确认机制
核心概念:
- 序列号:每个字节的数据都有唯一序列号(初始值随机,避免冲突),用于标识数据位置;
- 确认号:表示 "期望接收的下一个字节的序列号"(即已正确接收确认号之前的所有数据);
- 滑动窗口:接收方告知发送方的 "可用缓冲区大小",发送方最多发送窗口大小的未确认数据。
传输流程:
- 发送方将应用层数据拆分为 "报文段"(Segment),每个报文段包含序列号、数据、校验和等;
- 发送方根据滑动窗口大小发送报文段,无需等待逐个确认(流水线传输,提高效率);
- 接收方收到报文段后,校验无误则返回 ACK(包含确认号),并将数据暂存缓冲区;
- 发送方收到 ACK 后,滑动窗口后移,继续发送新数据;若超时未收到 ACK,则重传对应报文段。
3. 连接释放:四次挥手
目的:确保双方都已传输完所有数据,安全释放连接资源。
流程:
- FIN+ACK :主动关闭方(如客户端)发送
FIN报文(表示无数据要发送),请求关闭连接; - ACK :被动关闭方(如服务器)回复
ACK报文,确认收到 FIN(此时服务器仍可发送数据); - FIN+ACK :服务器发送完剩余数据后,发送
FIN报文,请求关闭连接; - ACK :客户端回复
ACK报文,确认收到 FIN(等待 2MSL 后彻底关闭连接,避免滞留的 FIN 报文引发问题)。
为什么需要四次挥手?
TCP 连接是全双工的,关闭时需分别关闭 "发送方向" 和 "接收方向":
- 第一次 FIN 关闭客户端→服务器的发送方向;
- 第三次 FIN 关闭服务器→客户端的发送方向;
- 两次 ACK 分别确认对方的关闭请求。
4. 拥塞控制机制
TCP 通过以下算法动态调整发送速率,适配网络状况:
- 慢启动:连接建立后,发送窗口从 1 开始指数增长,直到达到慢启动阈值;
- 拥塞避免:达到阈值后,窗口线性增长,避免过快引发拥塞;
- 快速重传:收到 3 个重复 ACK 时,立即重传丢失的报文段(无需等待超时);
- 快速恢复:重传后,窗口调整为慢启动阈值的一半,进入拥塞避免阶段。
三、TCP 的应用场景与局限性
1. 适用场景
- 对可靠性要求高的业务:网页访问(HTTPS)、文件传输(FTP/SFTP)、邮件收发(SMTP/POP3)、数据库连接(MySQL)、远程登录(SSH);
- 对数据完整性要求高于延迟的场景:金融交易、电商支付、大文件传输。
2. 局限性
- 延迟较高:三次握手、确认重传、拥塞控制等机制增加了传输延迟;
- 开销大:头部信息多(至少 20 字节),确认和重传消耗带宽;
- 不适合实时性要求高的场景:如直播、游戏、语音通话(这类场景优先用 UDP)。
四、TCP 与 UDP 的核心区别
|------|--------------|--------------|
| 特性 | TCP | UDP |
| 连接性 | 面向连接(三次握手) | 无连接 |
| 可靠性 | 可靠(确认、重传、排序) | 不可靠(无确认、无重传) |
| 传输方式 | 字节流 | 数据报(有消息边界) |
| 拥塞控制 | 支持 | 不支持 |
| 流量控制 | 支持(滑动窗口) | 不支持 |
| 头部开销 | 20~60 字节 | 8 字节 |
| 延迟 | 较高 | 较低 |
| 适用场景 | 网页、文件、邮件 | 直播、游戏、DNS 查询 |
tcp****相关函数
int socket(int domain, int type, int protocol);
功能:程序向内核提出创建一个基于内存的套接字描述符
参数:
- domain 地址族,PF_INET == AF_INET ==>互联网程序
- PF_UNIX == AF_UNIX ==>单机程序
type 套接字类型:
- SOCK_STREAM 流式套接字 ===》TCP
- SOCK_DGRAM 用户数据报套接字===>UDP
- SOCK_RAW 原始套接字 ===》IP
protocol 协议 ==》0 表示自动适应应用层协议。
返回值:
- 成功 返回申请的套接字id
- 失败 -1;
2、int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
功能:如果该函数在服务器端调用,则表示将参数1相关的文件描述符文件与参数2 指定的接口地址关联,用于从该接口接受数据。
3、 int listen(int sockfd, int backlog);
功能:在参数1所在的套接字id上监听等待链接。
参数:
- sockfd 套接字id
- backlog 允许三次握手的排队数。
返回值:
- 成功 0
- 失败 -1;
4、int accept(int sockfd, struct sockaddr *addr,socklen_t *addrlen);
功能:从已经监听到的队列中取出有效的客户端链接并接入到当前程序。
参数:
- sockfd 套接字id
- addr 如果该值为NULL ,表示不论客户端是谁都接入。如果要获取客户端信息,则事先定义变量并传入变量地址,函数执行完毕将会将客户端信息存储到该变量中。
- addrlen: 参数2的长度,如果参数2为NULL,则该值也为NULL;如果参数不是NULL,&len;一定要写成len = sizeof(struct sockaddr);
返回值:
- 成功 返回一个用于通信的新套接字id; 通信套接字从该代码之后所有通信都基于该id
- 失败 -1;
5.ssize_t recv(int sockfd, void *buf, size_t len,int flags);
功能:从指定的sockfd套接字中以flags方式获取长度为len字节的数据到指定的buff内存中。
参数:
- sockfd 如果服务器则是accept的返回值的新fd,如果客户端则是socket的返回值旧fd
- buff 用来存储数据的本地内存,一般是数组或者动态内存。
- len 要获取的数据长度
- flags 获取数据的方式,0 表示阻塞接受。
返回值:
- 成功 表示接受的数据长度,一般小于等于len
- 失败 -1;
- int send(int sockfd, const void *msg,size_t len, int flags);
功能:从msg所在的内存中获取长度为len的数据以flags方式写入到sockfd对应的套接字中。
参数:
-
sockfd:如果是服务器则是accept的返回值新fd,如果是客户端则是sockfd的返回值旧fd
-
msg 要发送的消息
-
len 要发送的消息长度
-
flags 消息的发送方式。
返回值:
- 成功 发送的字符长度
- 失败 -1;
客户端 自动连接服务器。
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能:该函数固定有客户端使用,表示从当前主机向目标主机发起链接请求。
参数:
- sockfd 本地socket创建的套接子id
- addr 远程目标主机的地址信息。
- addrlen: 参数2的长度。
返回值:
- 成功 0
- 失败 -1;
服务器客户端模型
cs ,client ,server
bs ,browser(浏览器),server
p2p peer to peer (对等的人)
|------|--------|-----------|------|-------|
| | 用途 | 使用协议 | 功能强弱 | 资源 |
| cs模型 | 专用客户段 | 应用,标准,自定义 | 相对复杂 | 资源在本地 |
| bs模型 | 通用的客户端 | 应用层 http | 相对简单 | 服务端发送 |