(一)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()操作。structpollfdfds[2];fds[0].fd=listen_fd;// 监听套接字fds[0].events=POLLIN;// 关注可读事件(新连接)fds[1].fd=client_fd;// 已连接的客户端fds[1].events=POLLIN;// 关注可读事件(收到数据)intret=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()阻塞等待事件。返回的事件数组只包含真正有活动的套接字。intefd=epoll_create1(0);structepoll_eventev,events[10];ev.events=EPOLLIN;// 关注可读事件ev.data.fd=listen_fd;epoll_ctl(efd,EPOLL_CTL_ADD,listen_fd,&ev);while(1){intn=epoll_wait(efd,events,10,-1);for(inti=0;i<n;++i){if(events[i].data.fd==listen_fd){// 有新连接intconn=accept(listen_fd,NULL,NULL);ev.events=EPOLLIN;ev.data.fd=conn;epoll_ctl(efd,EPOLL_CTL_ADD,conn,&ev);}else{// 已连接的客户端有数据可读charbuf[1024];ssize_tcnt=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)
intsock=socket(AF_INET,SOCK_STREAM,0);connect(sock,(structsockaddr*)&addr,sizeof(addr));send(sock,"hello",5,0);recv(sock,buf,sizeof(buf),0);close(sock);HTTP(curl)
curl-X GET https://api.example.com/usersSSE(浏览器)
constes=newEventSource('/sse/price');es.onmessage=e=>console.log('price:',e.data);WebSocket / WSS(浏览器)
constws=newWebSocket('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)
constclient=newPaho.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 示例(客户端)
fromsocketimport*server_name='127.0.0.1'# 服务器 IPserver_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 示例(服务器)
fromsocketimport*PORT=12000server=socket(AF_INET,SOCK_STREAM)server.bind(('',PORT))# 监听所有网卡server.listen(1)print('服务器已启动,等待连接…')whileTrue: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)
importsocket,select listen=socket.socket()listen.bind(('0.0.0.0',9000))listen.listen()poller=select.poll()poller.register(listen.fileno(),select.POLLIN)whileTrue:events=poller.poll()forfd,flaginevents:iffd==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)ifdata:conn.send(b'echo: '+data)else:# 客户端关闭poller.unregister(fd)conn.close()Python 示例(使用select.epoll)
importsocket,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)whileTrue:forfd,eventinep.poll():iffd==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)ifdata:conn.send(b'echo: '+data)else:ep.unregister(fd)conn.close()三、HTTP(超文本传输协议)
- 概念:基于 TCP 的请求‑响应协议。客户端(浏览器或程序)发送GET/POST等请求,服务器返回状态码 + 报文体。在 AI 业务中常用来提供RESTful API,让前端或其他服务通过 HTTP 调用模型推理接口。
- Python 示例(Flask 简单 HTTP 服务)
fromflaskimportFlask,request,jsonify app=Flask(__name__)@app.route('/hello')defhello():name=request.args.get('name','World')returnf'Hello,{name}!'@app.route('/predict',methods=['POST'])defpredict():data=request.json# 前端发送的 JSON# 这里可以调用模型进行推理,示例直接回显result={'input':data,'output':'dummy_result'}returnjsonify(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)
fromflaskimportFlask,Responseimporttime app=Flask(__name__)defevent_stream():i=0whileTrue:i+=1yieldf'data: 计数{i}\n\n'# 每秒推送一次time.sleep(1)@app.route('/counter')defcounter():returnResponse(event_stream(),mimetype='text/event-stream')if__name__=='__main__':app.run(threaded=True)# 必须开启多线程- 浏览器端(HTML)(仅示例,实际使用时放在前端页面)
<script>constes=newEventSource('/counter');es.onmessage=e=>console.log('服务器推送:',e.data);</script>五、WSS(WebSocket Secure)
- 概念:在 HTTP/HTTPS 端口上升级为全双工的WebSocket连接,
ws://为明文,wss://为 TLS 加密版。建立一次握手后,客户端和服务器都可以随时主动发送二进制或文本帧,延迟通常在毫秒级。适用于聊天、实时协作、在线游戏、AI 推理流式返回(如 ChatGPT 的流式输出)。 - Python 示例(使用
websockets库)
# server.pyimportasyncio,websocketsasyncdefecho(ws,path):asyncformsginws:awaitws.send(f'回显:{msg}')start_server=websockets.serve(echo,'0.0.0.0',8765,ssl=None)# 若要 wss,传入 ssl.SSLContextasyncio.get_event_loop().run_until_complete(start_server)asyncio.get_event_loop().run_forever()# client.pyimportasyncio,websocketsasyncdefhello():asyncwithwebsockets.connect('ws://127.0.0.1:8765')asws:awaitws.send('你好,服务器')reply=awaitws.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)
# publisher.pyimportpaho.mqtt.clientasmqtt broker='broker.hivemq.com'# 公共测试 brokerclient=mqtt.Client()client.connect(broker,1883,60)client.publish('demo/temperature',payload='23.5',qos=0)print('已发布温度 23.5')client.disconnect()# subscriber.pyimportpaho.mqtt.clientasmqttdefon_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(物联网、传感器网络、实时数据分发)