前面章节我们学习了应用层协议、进程通信等理论,而套接字(Socket) 就是把这些理论落地为代码的 “编程接口”—— 它是应用层与运输层之间的 “桥梁”,让我们能在代码里直接调用 TCP/UDP 服务,实现真正的网络应用。


2.7.1 UDP 套接字编程:无连接的高效通信

UDP 是无连接、不可靠的传输协议,对应到编程中,它的特点是 **“无需建立连接,直接发送数据”**,适合实时性要求高、对可靠性要求稍低的场景(如聊天、直播、DNS 查询)。

1. UDP 编程核心流程

以 Python 为例,UDP 通信分为服务器端客户端

服务器端(接收数据)
  1. 创建 UDP 套接字:socket(AF_INET, SOCK_DGRAM)
    • AF_INET:使用 IPv4 地址
    • SOCK_DGRAM:指定为 UDP 类型
  2. 绑定端口:bind((HOST, PORT)),监听指定端口的 incoming 数据
  3. 循环接收数据:recvfrom(BUFSIZE),同时获取客户端地址
  4. 处理数据并回复(可选):sendto(data, client_addr)
  5. 关闭套接字
客户端(发送数据)
  1. 创建 UDP 套接字(和服务器端一致)
  2. 直接发送数据:sendto(data, server_addr)无需提前连接
  3. 接收服务器回复(可选):recvfrom(BUFSIZE)
  4. 关闭套接字

2. 代码示例(Python)

# UDP 服务器
from socket import *
HOST = '127.0.0.1'
PORT = 12000
server_socket = socket(AF_INET, SOCK_DGRAM)
server_socket.bind((HOST, PORT))
print("UDP 服务器已启动,等待接收数据...")

while True:
    data, client_addr = server_socket.recvfrom(1024)
    print(f"收到来自 {client_addr} 的消息:{data.decode()}")
    server_socket.sendto(f"已收到:{data.decode()}".encode(), client_addr)

server_socket.close()
# UDP 客户端
from socket import *
server_addr = ('127.0.0.1', 12000)
client_socket = socket(AF_INET, SOCK_DGRAM)

message = "Hello UDP!"
client_socket.sendto(message.encode(), server_addr)
response, _ = client_socket.recvfrom(1024)
print(f"服务器回复:{response.decode()}")

client_socket.close()

3. UDP 编程特点

  • ✅ 无连接:客户端直接发送数据,不需要三次握手,开销小、速度快
  • ❌ 不可靠:不保证数据一定送达,也不保证顺序,丢包不会重传
  • ✅ 简单高效:代码逻辑简洁,适合实时性优先的场景

2.7.2 TCP 套接字编程:面向连接的可靠通信

TCP 是面向连接、可靠的传输协议,对应到编程中,它的特点是 **“先建立连接,再传输数据,保证可靠”**,适合对数据完整性要求高的场景(如文件传输、网页访问、邮件收发)。

1. TCP 编程核心流程

TCP 通信必须先建立连接,分为服务器端(被动监听)客户端(主动连接)

服务器端(监听 + 处理连接)
  1. 创建 TCP 套接字:socket(AF_INET, SOCK_STREAM)
    • SOCK_STREAM:指定为 TCP 类型
  2. 绑定端口:bind((HOST, PORT))
  3. 监听连接:listen(backlog)backlog 是等待连接的队列长度
  4. 接受连接:conn, addr = accept(),阻塞等待客户端连接,返回连接套接字
  5. 通过连接套接字收发数据:recv(BUFSIZE) / send(data)
  6. 关闭连接套接字,继续监听下一个连接
客户端(主动连接)
  1. 创建 TCP 套接字(和服务器端一致)
  2. 连接服务器:connect(server_addr),执行 TCP 三次握手
  3. 收发数据:send(data) / recv(BUFSIZE)
  4. 关闭套接字,执行 TCP 四次挥手

2. 代码示例(Python)

# TCP 服务器
from socket import *
HOST = '127.0.0.1'
PORT = 12000
server_socket = socket(AF_INET, SOCK_STREAM)
server_socket.bind((HOST, PORT))
server_socket.listen(5)
print("TCP 服务器已启动,等待客户端连接...")

while True:
    conn_socket, client_addr = server_socket.accept()
    print(f"客户端 {client_addr} 已连接")
    data = conn_socket.recv(1024)
    print(f"收到消息:{data.decode()}")
    conn_socket.send(f"已收到:{data.decode()}".encode())
    conn_socket.close()

server_socket.close()
# TCP 客户端
from socket import *
server_addr = ('127.0.0.1', 12000)
client_socket = socket(AF_INET, SOCK_STREAM)
client_socket.connect(server_addr)

message = "Hello TCP!"
client_socket.send(message.encode())
response = client_socket.recv(1024)
print(f"服务器回复:{response.decode()}")

client_socket.close()

3. TCP 编程特点

  • ✅ 面向连接:必须先 connect() 建立连接,才能传输数据
  • ✅ 可靠传输:内置重传、排序、流量控制,保证数据完整送达
  • ❌ 开销较大:三次握手、四次挥手、拥塞控制等机制会增加时延和资源消耗
  • ✅ 流式传输:数据以字节流形式传输,没有边界,需要应用层自己处理消息边界

✅ UDP vs TCP 编程对比

特性 UDP 套接字 TCP 套接字
连接方式 无连接,直接发送 面向连接,必须先 connect()
可靠性 不可靠,丢包不重传 可靠,保证数据完整有序
代码复杂度 简单,无需处理连接 稍复杂,需要监听、接受连接
适用场景 实时聊天、直播、DNS、游戏 文件传输、网页访问、邮件、数据库通信
核心 API sendto() / recvfrom() connect() / send() / recv()

🎯 编程实践建议

  1. 先跑通示例:把上面的 UDP/TCP 代码复制到本地运行,观察 “客户端发送→服务器接收→回复” 的完整流程
  2. 改造功能
    • 给 UDP 版本加一个简单的 “聊天功能”,让服务器可以广播消息给所有客户端
    • 给 TCP 版本加 “文件传输” 功能,实现客户端上传文件到服务器
  3. 对比差异:故意断开网络,观察 UDP 丢包、TCP 重传的不同表现,加深对协议特性的理解
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐