嵌入式从0到精通——Linux 网络通信|TCP、HTTP 网络编程

📝学习感悟

最近学完 Linux 下 TCP 以及 HTTP 网络编程部分,对比前面 UDP 通信,最大感受就是 TCP 虽然可靠性高,但内部机制复杂,坑点也更多。UDP 只管发出去就结束,而 TCP 要处理连接建立断开、丢包重传、流量控制,还会出现粘包这种容易踩坑的问题。

1.TCP 协议

传输层TCP: 传输控制协议 (流式套接字)

1. TCP 特点

  1. 有连接;
  2. 面向字节流;
  3. 安全可靠的传输协议三次握手、四次挥手、应答机制、超时重传机制.... 等
  4. 机制复杂,实时性和效率没有 UDP 高

应用场景:HTTPS、MQTT、FTP

2. TCP 的三次握手和四次挥手机制

三次握手:TCP 建立连接时,通过三次握手,来确保通信双方都已经准备就绪。三次握手由客户端发起。

数据收发:

四次挥手:TCP 断开连接时,通过四次挥手,确保通信双方数据都已经收发结束。

3. TCP 编程

客户端流程:socket()-->connect()-->send()-->recv()-->close()

服务端流程:socket()-->bind()-->listen()-->accept()-->recv()-->send()-->close()

connect
复制代码
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

功能:请求建立连接参数:

  • sockfd:套接字
  • addr:服务端的地址
  • addrlen:地址长度返回值:
  • 成功:0
  • 失败:-1
listen
复制代码
int listen(int sockfd, int backlog);

功能:监听客户端的三次握手参数:

  • sockfd:监听套接字
  • backlog:最多允许监听的客户端的个数返回值:
  • 成功:0
  • 失败:-1
accept
复制代码
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

功能:接收完成三次握手的客户端,并返回一个通讯套接字参数:

  • sockfd:监听套接字
  • addr:保存接入的客户端的地址信息的指针
  • addrlen:地址信息长度的指针返回值:
  • 成功:通讯套接字
  • 失败:-1
recv
复制代码
ssize_t recv(int sockfd, void *buf, size_t len, int flags);

功能:接收网络数据参数:

  • sockfd:通讯套接字
  • buf:存放接收到的数据的空间首地址
  • len:期待接收到的字节数
  • flags:0 默认方式返回值:
  • 成功:返回实际收到的字节数
  • 失败:-1

返回 0 代表对方发送断开连接

4. TCP 报文头部

标志位:TCP 报文头部数据位:

  • SYN:请求建立连接标志位
  • ACK:效应报文标志位
  • PSH:携带数据的报文标志位
  • FIN:请求断开连接标志位
  • URG:紧急数据标志位
  • RST:重置标志位

5. TCP 机制

  1. 三次握手机制:建立连接,确认双方收发能力正常
  2. 四次挥手机制:断开连接,保证双方数据全部处理完毕
  3. 应答机制:TCP 为发送的数据进行编号,发送数据时,报文头部的序列号是这包数据的第一个数据的编号;将来接收方需要给这包数据发送 ACK,ACK 报文中确认号是收到的最后一个字节编号 + 1;
  4. 超时重传机制:TCP 每发送一包数据后都要等待应答,如果超时时间之内没有收到应答,则重新发送这包数据。
  5. 滑动窗口机制:缓冲区,保存已发送并收到应答的数据、已发送未收到应答的数据、未发送但在对方处理范围内的数据。
  6. 延迟应答机制:TCP 可以发送多组数据,发送的同时等待应答。
  7. 流量控制机制:TCP 会根据发送端的数据处理和接收能力调整自己的发送速率,根据 ACK 中窗口值的大小进行动态调整流量。
  8. 捎带应答机制:ACK 可以和应用层发送的数据一起发出,表示对上包数据的响应。

6. TCP 粘包

粘包:发送端发送速度太快,接收端处理速度比较慢,导致数据在缓冲区缓存,应用层读出数据时,多包数据发生了粘连。

如何解决:

  1. 收发指定大小数据 (收发结构体)

注意:跨平台发送时平台的位数。

复制代码
struct data
{
    xxx;
    long num;
};
send(sockfd, &data, sizeof(struct data), 0);
recv(sockfd, &data, sizeof(struct data), 0);
  1. 给发送的数据明显的分割符,应用层根据分隔符解析 例:hello\nworld\n,接收端按换行符分割解析。

  2. 以自定义方式定义发送的数据帧格式,接收方严格按照协议方式解析 帧格式示例:帧头 数据长度 消息类型 校验 帧尾示例:5A 0101 1010 A5校验可选:8 位和校验、16 位和校验、CRC 校验。


2.HTTP 协议

应用层HTTP 协议:超文本传输协议基于传输层 TCP 协议,端口 80HTTPS:SSL 加密方式,默认端口 443

1. HTTP 协议工作流程

  1. 建立 TCP 连接
  2. 发送 HTTP 请求报文(URL)+ 正文
  3. 返回 HTTP 响应报文 + 正文
  4. 断开 TCP 连接

2. HTTP 报文

HTTP 有两类报文:

  1. 请求报文:从客户向服务器发送请求报文
  2. 响应报文:从服务器到客户的回答

HTTP 报文每一个字段都是 ASCII 码串,字段长度不确定。

http 请求报文示例
复制代码
GET / HTTP/1.1\r\n
Host: news.sohu.com\r\n
User‑Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/113.0\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept‑Language: en‑US,en;q=0.5\r\n
Connection: keep‑alive\r\n
\r\n
  • keep‑alive:长连接,HTTP 通信结束,保持一段时间连接再断开
  • close:短连接,HTTP 通信结束,立马断开连接
HTTP 响应报文示例
复制代码
HTTP/1.1 200 OK\r\n
Date: Wed, 02 Sep 2026 06:31:29 GMT\r\n
Content‑Type: text/html;charset=utf‑8\r\n
Server: openresty
Vary: Accept‑Encoding
Vary: Origin
Vary: Accept‑Request‑Method
Vary: Access‑Control‑Request‑Headers
Set‑Cookie: SUV=1788330689823odinzX9W; Path=/; Domain=sohu.com; Max‑Age=946080000; Expires=Fri, 25 Aug 2056 06:31:29 GMT; Secure; SameSite=None
Trace‑Id: a067a38f132249f8a173162c956fc468.88701.17883306898232510
Data‑Source: 
X‑Content‑Type‑Options: nosniff
X‑XSS‑Protection: 0
S‑REQ‑ID: 12342245799539308391
S‑REQ‑TYPE: 0
X‑Cache‑Lookup: Cache Miss
Content‑Encoding: gzip
Cache‑Control: no‑cache
Transfer‑Encoding: chunked
X‑NWS‑LOG‑UUID: 12342245799539308391\r\n
Connection: keep‑alive\r\n
X‑Cache‑Lookup: Cache Miss\r\n
\r\n
<!DOCTYPE html><html lang=zh‑CN><head>
<script>if(window&&window.performance&&typeof window.performance.now==='function'){

3.HTTP 常用方法

方法 (操作) 意义
GET 获取资源
POST 提交数据
PUT 在指明的 URL 下存储一个文档
DELETE 删除资源

4.HTTP 状态码

状态码都是三位数字,分为 5 大类:

  1. 1xx:通知信息,请求收到,正在进行处理
  2. 2xx:成功,请求正常处理
  3. 3xx:重定向,需要进一步操作完成请求
  4. 4xx:客户端差错,请求语法错误 / 资源不存在
  5. 5xx:服务器差错,服务器内部异常

常见状态码:

  • 200 OK:请求成功
  • 202 Accepted:接受请求
  • 400 Bad Request:错误的请求
  • 404 Not Found:找不到资源

5.http 接口调用示例

plaintext

复制代码
http://api.k780.com/?app=weather.today&cityNm=西安&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json
  • appkey:平台分配密钥
  • sign:签名校验
  • format=json:返回 json 格式数据

学习小结

  1. TCP 是面向连接可靠字节流协议,核心机制:三次握手、四次挥手、应答、超时重传、流量控制、滑动窗口;
  2. TCP 粘包是缓冲区现象,不是 bug,三种主流解决方案:固定结构体、分隔符、自定义帧协议;
  3. HTTP 基于 TCP,文本格式报文,区分长短连接,状态码区分请求结果;
  4. 实际开发嵌入式 Linux 网络编程,TCP 粘包是高频踩坑点,写代码的时候必须提前规划数据协议
相关推荐
姚不倒1 小时前
Tengine 实战:主动健康检查 + 动态 Upstream 配置
运维·网络·nginx
茶栀(*´I`*)1 小时前
Python网络机器人入门:从Robots协议、网页结构到Requests库的基础实践
网络·python·机器人
Ai思想家1 小时前
一次模型调用会留下什么:聚合平台的日志留存与数据边界
大数据·服务器·网络·人工智能
筝筝ba2 小时前
linux查询某个网卡是否插了对应网线的命令
linux·运维·网络
小宏运维有点菜2 小时前
Raid-1安装Ubuntu 24.04 LTS
linux·运维·服务器
姚不倒2 小时前
HAProxy 系列(二):健康检查与 SSL 卸载 — 保障可用性与性能
运维·网络·网络协议·ssl·haproxy
内核笔记2 小时前
内核调用栈调试
linux·单片机·bsp
qetfw2 小时前
Debian Nginx + PHP-FPM 配置:FastCGI、站点目录与访问验证
linux·nginx·debian·php
ue星空2 小时前
登录失败:failed to start login server: 以一种访问权限不允许的方式做了一个访问套接字的尝试。 (os error 10013)
网络·codex