网络编程—TCP传输控制协议

TCP(Transmission Control Protocol,传输控制协议)是 TCP/IP 模型传输层的核心协议,专为可靠、有序、面向连接的端到端数据传输设计,是互联网中绝大多数关键应用(如网页访问、文件传输、邮件收发)的底层支撑

一、TCP 的核心特性

1. 面向连接

TCP 通信前必须先建立端到端的连接(三次握手),通信结束后需释放连接(四次挥手),类似 "打电话"(先拨号接通,再通话,最后挂电话)。

  • 连接是全双工的:双方可同时发送和接收数据;
  • 连接基于 "四元组" 标识:源 IP、源端口、目的 IP、目的端口(唯一确定一个 TCP 连接)。

2. 可靠传输

TCP 通过一系列机制保证数据无丢失、无重复、按序到达

  • 确认应答(ACK):接收方收到数据后必须向发送方返回确认;
  • 超时重传:发送方若超时未收到确认,自动重传数据;
  • 差错校验:通过校验和检测数据是否损坏,损坏则丢弃并触发重传;
  • 重排乱序包:接收方对乱序到达的数据包重新排序,按序交付给应用层;
  • 丢弃重复包:通过序列号识别重复数据并丢弃。

3. 字节流传输

TCP 将应用层数据视为连续的 "字节流",无消息边界(这也是粘包问题的根源),仅保证字节的顺序和完整性,不关心应用层的消息划分。

4. 流量控制

TCP 通过滑动窗口机制控制发送方的传输速率,避免接收方缓冲区溢出(接收方通过窗口大小告知发送方 "最多还能接收多少数据")。

5. 拥塞控制

TCP 通过算法感知网络拥塞(如丢包、延迟增加),动态调整发送速率,避免加剧网络拥堵(核心算法:慢启动、拥塞避免、快速重传、快速恢复)。

二、TCP 的核心工作机制

1. 连接建立:三次握手

目的:同步双方的序列号和确认号,分配资源(如缓冲区),确保双方收发能力正常。
流程:

  1. SYN:客户端向服务器发送 SYN 报文(同步序列号,初始序列号为 x),请求建立连接;
  2. SYN+ACK:服务器收到后,回复 SYN+ACK 报文(同步自己的初始序列号 y,确认客户端的 x+1);
  3. ACK:客户端收到后,回复 ACK 报文(确认服务器的 y+1),连接正式建立。

为什么需要三次握手?

  • 防止 "失效的连接请求报文段" 被服务器接收(如客户端发送的 SYN 报文因网络延迟滞留,后续重发并建立连接,滞留的 SYN 后续到达服务器,若两次握手则服务器会建立无效连接,浪费资源);
  • 同步双方的序列号(TCP 依赖序列号实现可靠传输)。

2. 数据传输:滑动窗口 + 确认机制

核心概念:

  • 序列号:每个字节的数据都有唯一序列号(初始值随机,避免冲突),用于标识数据位置;
  • 确认号:表示 "期望接收的下一个字节的序列号"(即已正确接收确认号之前的所有数据);
  • 滑动窗口:接收方告知发送方的 "可用缓冲区大小",发送方最多发送窗口大小的未确认数据。

传输流程:

  1. 发送方将应用层数据拆分为 "报文段"(Segment),每个报文段包含序列号、数据、校验和等;
  2. 发送方根据滑动窗口大小发送报文段,无需等待逐个确认(流水线传输,提高效率);
  3. 接收方收到报文段后,校验无误则返回 ACK(包含确认号),并将数据暂存缓冲区;
  4. 发送方收到 ACK 后,滑动窗口后移,继续发送新数据;若超时未收到 ACK,则重传对应报文段。

3. 连接释放:四次挥手

目的:确保双方都已传输完所有数据,安全释放连接资源。

流程:

  1. FIN+ACK :主动关闭方(如客户端)发送 FIN 报文(表示无数据要发送),请求关闭连接;
  2. ACK :被动关闭方(如服务器)回复 ACK 报文,确认收到 FIN(此时服务器仍可发送数据);
  3. FIN+ACK :服务器发送完剩余数据后,发送 FIN 报文,请求关闭连接;
  4. 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;
  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 | 相对简单 | 服务端发送 |

相关推荐
云老大TG:@yunlaoda3602 小时前
华为云国际站代理商DAS的跨境合规适配是如何保障数据合规的?
网络·数据库·华为云
TG:@yunlaoda360 云老大2 小时前
华为云国际站代理商HiLens的技术优势对跨境客户有哪些具体帮助?
服务器·数据库·华为云
科技块儿2 小时前
【账号安全预警】如何基于IP查询进行登录异常识别、账号防盗?
网络协议·tcp/ip·安全
TG:@yunlaoda360 云老大2 小时前
华为云国际站代理商DAS的跨境合规适配在游戏出海场景中的应用
服务器·网络·游戏·华为云
没有bug.的程序员2 小时前
熔断、降级、限流:高可用架构的三道防线
java·网络·jvm·微服务·架构·熔断·服务注册
TG:@yunlaoda360 云老大3 小时前
华为云国际站代理商的DDM主要有什么作用呢?
服务器·数据库·华为云
wregjru3 小时前
【操作系统】linux常用指令
linux·运维·服务器
咕噜签名-铁蛋3 小时前
双雄争霸:Windows与Linux操作系统的技术博弈与生态进化
服务器
笨笨马甲3 小时前
Qt TCP连接硬件设备
开发语言·qt·tcp/ip