(一)TCP、poll、epoll
TCP(传输控制协议)
- 是什么 :TCP 是一种面向连接、可靠的网络传输协议。它把要发送的大块数据切成一个个"小段"(称为报文段),并在发送前为每段加上序号。接收方收到后会给发送方回送确认(ACK),如果发送方在一定时间内没有收到确认,就会重新发送该段。
- 通俗比喻:想象你在写信寄快递,每封信都有编号,收件人收到后会回一张收据。如果寄出的信件丢了,你会再寄一遍,直到收到收据为止。
- 开发实例 :在 C/C++ 中使用
socket()、connect()、send()、recv()等系统调用即可实现基于 TCP 的客户端/服务器。例如,一个最简单的回显服务器会在recv()读取到客户端发来的数据后,直接用send()把相同的数据返回给客户端。
poll(轮询)
-
是什么 :
poll是一种 I/O 多路复用 的系统调用。它让一个进程一次性监视 多个文件描述符(如套接字、管道、文件等)的状态(是否可读、可写、异常等),并在有任意一个描述符准备好时返回。 -
通俗比喻:想象你是老师,要检查一堆学生的作业是否完成。你一次性把所有作业本都摆在桌子上,等到有学生把作业交上来,你立刻看到并批改,而不必一个一个去叫学生。
-
开发实例 :在 Linux 下,使用
struct pollfd数组把所有要监听的套接字放进去,然后调用poll(pfds, nfds, timeout)。返回后遍历数组,找到revents标记为可读或可写的套接字进行相应的recv()/send()操作。cstruct pollfd fds[2]; fds[0].fd = listen_fd; // 监听套接字 fds[0].events = POLLIN; // 关注可读事件(新连接) fds[1].fd = client_fd; // 已连接的客户端 fds[1].events = POLLIN; // 关注可读事件(收到数据) int ret = poll(fds, 2, -1); // 阻塞等待 if (fds[0].revents & POLLIN) { /* accept new connection */ } if (fds[1].revents & POLLIN) { /* recv data */ }
epoll(高效的 I/O 多路复用)
-
是什么 :
epoll是 Linux 为了解决poll/select在 大规模并发 场景下性能瓶颈而推出的专用机制。它采用 事件驱动 的方式,只在真正有状态变化的文件描述符上触发回调,避免每次轮询都遍历全部描述符。 -
通俗比喻:继续老师的例子。如果班里有几千名学生,你不可能每次都把所有作业本都搬到桌子上检查。于是你让每个学生在作业完成后主动把作业本递到老师面前,老师只需要处理递来的作业本,效率大大提升。
-
开发实例 :使用
epoll_create1()创建 epoll 实例,epoll_ctl()把感兴趣的套接字加入(或删除)监视集合,epoll_wait()阻塞等待事件。返回的事件数组只包含真正有活动的套接字。cint efd = epoll_create1(0); struct epoll_event ev, events[10]; ev.events = EPOLLIN; // 关注可读事件 ev.data.fd = listen_fd; epoll_ctl(efd, EPOLL_CTL_ADD, listen_fd, &ev); while (1) { int n = epoll_wait(efd, events, 10, -1); for (int i = 0; i < n; ++i) { if (events[i].data.fd == listen_fd) { // 有新连接 int conn = accept(listen_fd, NULL, NULL); ev.events = EPOLLIN; ev.data.fd = conn; epoll_ctl(efd, EPOLL_CTL_ADD, conn, &ev); } else { // 已连接的客户端有数据可读 char buf[1024]; ssize_t cnt = read(events[i].data.fd, buf, sizeof(buf)); // 处理数据... } } }
小结
| 名称 | 作用 | 适用场景 | 关键特性 |
|---|---|---|---|
| TCP | 可靠的点对点数据传输 | 需要保证数据完整性(文件传输、网页请求等) | 连接、序号、确认、重传 |
| poll | 同时监视多个 I/O 对象的状态 | 连接数不多、代码简单的服务器 | 每次调用遍历全部描述符 |
| epoll | 高效监视大量 I/O 对象 | 高并发服务器(成千上万连接) | 只返回活跃描述符,性能更好 |
(二)TCP、http、sse、wss、mqtt通讯协议对比
一、基本概念(通俗版)
| 名称 | 所在层次 | 关键特性 | 典型使用场景 |
|---|---|---|---|
| TCP | 传输层(OSI 第 4 层) | 面向连接、可靠、全双工、基于字节流、通过三次握手/四次挥手建立和关闭连接 | 文件传输、网页请求、任何需要保证数据不丢失的场景 |
| HTTP | 应用层(基于 TCP) | 请求‑响应模型、无状态、默认端口 80(HTTPS 443),支持 GET/POST 等方法 | 浏览器访问网页、REST API、静态资源下载 |
| SSE(Server‑Sent Events) | 基于 HTTP 的单向推送 | 服务器单向向浏览器推送文本/JSON,自动重连,使用普通 HTTP(或 HTTPS)长连接 | 新闻、股票行情、系统通知等只需要服务器"推送"而不需要客户端回传的实时更新 |
| WSS(WebSocket Secure) | 基于 TCP 的全双工协议(加密版) | 在 WebSocket(ws://)之上加入 TLS/SSL 加密,URL 以 wss:// 开头,提供双向实时通信 |
在线聊天、实时协作、游戏等对安全有要求的双向交互 |
| MQTT | 基于 TCP(可选 TLS) 的轻量级发布‑订阅协议 | 采用 Broker 中转,支持 QoS 0/1/2,报文头极小,适合低带宽、低功耗设备 | 物联网传感器、远程监控、移动端轻量消息推送 |
二、技术对比与选型指南
-
传输可靠性 vs 交互模式
- TCP 提供可靠的点对点传输,是所有上层协议(HTTP、WebSocket、MQTT)的基石。
- HTTP 只负责一次请求‑响应,适合"拉取"数据的场景。
- SSE 在 HTTP 长连接上实现单向 推送,代码只需在浏览器端
new EventSource(url),不需要自己维护心跳或重连逻辑。 - WebSocket / WSS 实现全双工 通信,客户端
new WebSocket(url),服务器可以随时主动发送,也能随时接收客户端消息。 - MQTT 采用发布‑订阅模型,客户端不直接相互通信,而是通过 Broker 进行主题(topic)转发,天然支持多对多广播。
-
性能与资源消耗
- SSE 只支持文本(JSON)数据,协议开销极小,适合数千级别的单向推送[[6]]。
- WebSocket(WSS)在保持一个 TCP 连接的前提下,能够以毫秒级延迟双向传输,适合高频交互(聊天、游戏)[[7]]。
- MQTT 报文头只有 2‑4 字节,QoS 机制可以在网络不佳时自动重传或丢弃,极其适合成千上万的物联网设备[[8]]。
-
安全性
- HTTP → HTTPS (TLS)可加密;WebSocket → WSS 同理,使用
wss://即可在传输层提供加密[[9]]。 - SSE 也可以通过 HTTPS(
https://)实现加密,只是协议本身不自带加密层。 - MQTT 支持基于 TLS 的 MQTTS (
mqtts://),在需要机密传输的工业场景中常用。
- HTTP → HTTPS (TLS)可加密;WebSocket → WSS 同理,使用
-
典型开发示例(代码片段)
-
TCP(C)
cint sock = socket(AF_INET, SOCK_STREAM, 0); connect(sock, (struct sockaddr*)&addr, sizeof(addr)); send(sock, "hello", 5, 0); recv(sock, buf, sizeof(buf), 0); close(sock); -
HTTP(curl)
bashcurl -X GET https://api.example.com/users -
SSE(浏览器)
jsconst es = new EventSource('/sse/price'); es.onmessage = e => console.log('price:', e.data); -
WebSocket / WSS(浏览器)
jsconst ws = new WebSocket('wss://chat.example.com'); ws.onopen = () => ws.send(JSON.stringify({type:'join',room:1})); ws.onmessage = e => console.log('msg:', e.data); -
MQTT(JavaScript Paho)
jsconst client = new Paho.MQTT.Client('broker.example.com', 8883, 'web_' + Math.random()); client.connect({useSSL:true, onSuccess:()=>{ client.subscribe('sensor/+/temp'); }}); client.onMessageArrived = msg => console.log(msg.topic, msg.payloadString);
-
-
选型小结
| 场景 | 推荐协议 | 说明 |
|---|---|---|
| 普通网页请求、REST API | HTTP/HTTPS | 简单请求‑响应,易于缓存、CDN |
| 只需要服务器单向实时推送(新闻、监控) | SSE(HTTPS) | 实现最简单,自动重连,浏览器原生支持 |
| 双向实时交互且对延迟敏感(聊天、协作、游戏) | WebSocket / WSS | 全双工、低延迟,安全版使用 WSS |
| 大量低功耗设备、需要主题广播、带 QoS | MQTT(MQTTS) | 轻量、发布‑订阅、可伸缩,适合物联网 |
| 需要可靠的点对点传输(文件、流媒体) | TCP(配合上层协议) | 为上层协议提供可靠通道 |
三、总结
- TCP 是所有网络通信的可靠基石。
- HTTP 基于 TCP,适合一次性请求‑响应。
- SSE 在 HTTP 长连接上实现单向推送,代码最简。
- WSS 是加密版 WebSocket,提供全双工实时通信并保证安全。
- MQTT 采用轻量的发布‑订阅模型,专为海量物联网设备设计。
根据业务需求(单向推送 vs 双向交互、设备规模、带宽限制、安全要求),在上述协议中挑选最合适的即可实现高效、可靠的网络通信。
(三)python实现示例
一、TCP(传输控制协议)
- 概念 :TCP 是面向连接、可靠的传输层协议。发送方把要发送的字节流切成若干报文段 ,每段都有序号;接收方收到后会回送 ACK(确认),发送方若在超时时间内未收到 ACK 就会重新发送该段。这样可以保证数据不丢失、顺序不乱。
- Python 示例(客户端)
python
from socket import *
server_name = '127.0.0.1' # 服务器 IP
server_port = 12000 # 服务器端口
client = socket(AF_INET, SOCK_STREAM)
client.connect((server_name, server_port))
msg = input('输入一句话:')
client.send(msg.encode()) # 发送
reply = client.recv(1024).decode() # 接收
print('服务器返回:', reply)
client.close()
- Python 示例(服务器)
python
from socket import *
PORT = 12000
server = socket(AF_INET, SOCK_STREAM)
server.bind(('', PORT)) # 监听所有网卡
server.listen(1)
print('服务器已启动,等待连接...')
while True:
conn, addr = server.accept()
data = conn.recv(1024).decode()
conn.send(data.upper().encode()) # 把收到的内容转成大写再回传
conn.close()
二、poll 与 epoll(I/O 多路复用)
- poll :一次性把多个文件描述符(套接字、文件等)放进
pollfd数组,调用poll()后内核会检查哪些描述符已经准备好(可读、可写、异常),返回后只处理这些"活跃"的描述符。适用于几百到几千个连接,但每次调用都要遍历整个数组。 - epoll (Linux 专有):采用 事件驱动 ,只在真正有状态变化的描述符上触发回调,内部使用红黑树 + 双向链表,避免每次遍历,能够轻松支撑 上万甚至上百万 并发连接。
Python 示例(使用 select.poll)
python
import socket, select
listen = socket.socket()
listen.bind(('0.0.0.0', 9000))
listen.listen()
poller = select.poll()
poller.register(listen.fileno(), select.POLLIN)
while True:
events = poller.poll()
for fd, flag in events:
if fd == listen.fileno():
conn, _ = listen.accept()
poller.register(conn.fileno(), select.POLLIN)
else:
conn = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM)
data = conn.recv(1024)
if data:
conn.send(b'echo: ' + data)
else: # 客户端关闭
poller.unregister(fd)
conn.close()
Python 示例(使用 select.epoll)
python
import socket, select
listen = socket.socket()
listen.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
listen.bind(('0.0.0.0', 9001))
listen.listen()
ep = select.epoll()
ep.register(listen.fileno(), select.EPOLLIN)
while True:
for fd, event in ep.poll():
if fd == listen.fileno():
conn, _ = listen.accept()
ep.register(conn.fileno(), select.EPOLLIN)
else:
conn = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM)
data = conn.recv(1024)
if data:
conn.send(b'echo: ' + data)
else:
ep.unregister(fd)
conn.close()
三、HTTP(超文本传输协议)
- 概念 :基于 TCP 的请求‑响应协议。客户端(浏览器或程序)发送 GET/POST 等请求,服务器返回 状态码 + 报文体 。在 AI 业务中常用来提供 RESTful API,让前端或其他服务通过 HTTP 调用模型推理接口。
- Python 示例(Flask 简单 HTTP 服务)
python
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/hello')
def hello():
name = request.args.get('name', 'World')
return f'Hello, {name}!'
@app.route('/predict', methods=['POST'])
def predict():
data = request.json # 前端发送的 JSON
# 这里可以调用模型进行推理,示例直接回显
result = {'input': data, 'output': 'dummy_result'}
return jsonify(result)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000) # 运行在 5000 端口
四、SSE(Server‑Sent Events)
- 概念 :在 HTTP 长连接上单向推送数据的技术。服务器端返回
Content-Type: text/event-stream,随后不断发送data: ...\n\n格式的文本。浏览器端使用EventSource接收,适合 实时监控、日志推送、股票行情 等只需要服务器主动推送的场景。 - Python 示例(Flask 实现 SSE)
python
from flask import Flask, Response
import time
app = Flask(__name__)
def event_stream():
i = 0
while True:
i += 1
yield f'data: 计数 {i}\n\n' # 每秒推送一次
time.sleep(1)
@app.route('/counter')
def counter():
return Response(event_stream(),
mimetype='text/event-stream')
if __name__ == '__main__':
app.run(threaded=True) # 必须开启多线程
- 浏览器端(HTML)(仅示例,实际使用时放在前端页面)
html
<script>
const es = new EventSource('/counter');
es.onmessage = e => console.log('服务器推送:', e.data);
</script>
五、WSS(WebSocket Secure)
- 概念 :在 HTTP/HTTPS 端口上升级为全双工的 WebSocket 连接,
ws://为明文,wss://为 TLS 加密版。建立一次握手后,客户端和服务器都可以随时主动发送二进制或文本帧,延迟通常在毫秒级。适用于 聊天、实时协作、在线游戏、AI 推理流式返回(如 ChatGPT 的流式输出)。 - Python 示例(使用
websockets库)
python
# server.py
import asyncio, websockets
async def echo(ws, path):
async for msg in ws:
await ws.send(f'回显:{msg}')
start_server = websockets.serve(echo, '0.0.0.0', 8765, ssl=None) # 若要 wss,传入 ssl.SSLContext
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
python
# client.py
import asyncio, websockets
async def hello():
async with websockets.connect('ws://127.0.0.1:8765') as ws:
await ws.send('你好,服务器')
reply = await ws.recv()
print('服务器说:', reply)
asyncio.get_event_loop().run_until_complete(hello())
如果需要 wss (加密),只需在 websockets.serve 与 websockets.connect 中传入 ssl 参数,使用 ssl.SSLContext 加载证书即可。
六、MQTT(Message Queuing Telemetry Transport)
- 概念 :轻量级的 发布‑订阅 协议,基于 TCP(可选 TLS)。客户端 publish 消息到某个 topic ,Broker 再把该 topic 的所有 subscriber 推送过去。报文头只有几字节,非常适合 物联网、边缘设备、实时数据流。
- Python 示例(使用
paho-mqtt)
python
# publisher.py
import paho.mqtt.client as mqtt
broker = 'broker.hivemq.com' # 公共测试 broker
client = mqtt.Client()
client.connect(broker, 1883, 60)
client.publish('demo/temperature', payload='23.5', qos=0)
print('已发布温度 23.5')
client.disconnect()
python
# subscriber.py
import paho.mqtt.client as mqtt
def on_message(client, userdata, msg):
print(f'收到主题 {msg.topic}: {msg.payload.decode()}')
broker = 'broker.hivemq.com'
client = mqtt.Client()
client.on_message = on_message
client.connect(broker, 1883, 60)
client.subscribe('demo/temperature')
client.loop_forever() # 持续监听
- 适用场景 :
- TCP:需要可靠、顺序的数据传输(文件、数据库同步)。
- poll/epoll :服务器需要同时管理大量长连接,epoll 在高并发下性能最佳。
- HTTP :一次性请求‑响应,适合 REST API、模型推理的同步调用。
- SSE:服务器单向推送实时更新,客户端不需要发送数据(如日志、监控面板)。
- WSS :全双工、低延迟,适合 聊天、协作编辑、流式 AI 输出。
- MQTT :轻量、主题广播,适合 IoT 设备、边缘计算、海量传感器数据。
小结(适用场景对照)
- 可靠点对点 → TCP(如文件传输、远程调用)
- 大量并发、需要高效轮询 → epoll(高并发 Web 服务、游戏服务器)
- 一次性请求‑响应 → HTTP(RESTful API、模型同步推理)
- 服务器单向推送 → SSE(实时监控、新闻推送)
- 全双工实时交互 → WSS(聊天、协作、流式 AI)
- 轻量发布‑订阅 → MQTT(物联网、传感器网络、实时数据分发)