TCP 协议

TCP 是面向连接、可靠的传输层协议。

特点:

  • 面向连接
  • 可靠传输
  • 有序传输
  • 面向字节流
  • 有流量控制
  • 有拥塞控制

适合:

  • HTTP/HTTPS
  • 文件传输
  • 数据库连接
  • 邮件传输

TCP 三次握手

建立连接需要三次握手:

1
2
3
4
客户端                           服务端
| -------- SYN -------------> |
| <----- SYN + ACK ---------- |
| -------- ACK -------------> |

目的:

  • 确认双方收发能力正常
  • 协商初始序列号

TCP 四次挥手

关闭连接通常需要四次挥手:

1
2
3
4
5
主动关闭方                       被动关闭方
| -------- FIN -------------> |
| <------- ACK -------------- |
| <------- FIN -------------- |
| -------- ACK -------------> |

注意:

  • TCP 是全双工协议
  • 一方关闭发送方向,不代表另一方也立即关闭

TCP 粘包与拆包

TCP 是字节流协议,不保留消息边界。

例如客户端发送:

1
2
send("hello")
send("world")

服务端可能收到:

1
"helloworld"

也可能收到:

1
2
"hel"
"loworld"

解决方法:

方法一:固定长度

每个包长度固定。

方法二:特殊分隔符

例如以 \n 作为消息结束。

1
2
hello\n
world\n

方法三:长度字段

包头包含数据长度。

1
| 4字节长度 | 数据内容 |

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>

bool sendPacket(int fd, const std::string& data) {
uint32_t len = htonl(data.size());

if (send(fd, &len, sizeof(len), 0) != sizeof(len)) {
return false;
}

if (send(fd, data.data(), data.size(), 0) != (ssize_t)data.size()) {
return false;
}

return true;
}

实际工程中还需要处理 send() 没有一次性发送完的情况。

UDP 协议

UDP 是无连接、不可靠、面向数据报的传输层协议。

特点:

  • 无连接
  • 不保证可靠
  • 不保证顺序
  • 不保证不重复
  • 保留消息边界
  • 开销小、速度快

适合:

  • DNS
  • 直播
  • 语音/视频通话
  • 游戏同步
  • 局域网广播

TCP 与 UDP 对比

对比项 TCP UDP
是否连接 面向连接 无连接
可靠性 可靠 不可靠
顺序 保证顺序 不保证
消息边界 无,字节流 有,数据报
速度 较慢 较快
使用场景 文件、网页、数据库 视频、游戏、DNS

HTTP 简介

HTTP 是应用层协议,通常基于 TCP。

常见方法:

方法 说明
GET 获取资源
POST 提交数据
PUT 更新资源
DELETE 删除资源

HTTP 报文格式:

1
2
3
GET /index.html HTTP/1.1
Host: example.com

HTTP 响应:

1
2
3
4
5
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 13

Hello, world!