Socket 编程详解(含 TCP 和 UDP 示例)
Socket 编程详解(含 TCP 和 UDP 示例)
一、什么是 Socket?
Socket(套接字)是计算机网络编程中用于进程间通信的接口,允许不同主机上的程序通过网络发送和接收数据。
你可以把它类比成一根“数据管道”,程序通过这根管道与远程设备进行交流。
二、Socket 的作用和优势
- ✅ 数据传输基础:实现网络通信的核心工具。
- ✅ 跨平台通用:支持几乎所有操作系统和编程语言。
- ✅ 支持多协议:可配合 TCP(可靠)或 UDP(高效)等协议使用。
- ✅ 灵活强大:能处理各种网络通信需求,如网页、聊天、游戏等。
三、Socket 的主要类型
类型 | 协议 | 特点 | 应用场景 |
---|---|---|---|
TCP Socket | TCP | 面向连接、可靠传输、一对一通信 | 网页浏览、文件传输 |
UDP Socket | UDP | 无连接、快速传输、支持广播 | 视频直播、在线游戏 |
四、Socket 常用方法速查表
4.1 通用方法
方法 | 作用说明 | 适用协议 |
---|---|---|
bind((ip,port)) | 绑定服务端地址 | TCP/UDP |
close() | 关闭连接 | 通用 |
4.2 TCP专用方法
方法 | 说明 |
---|---|
listen(backlog) | 启动监听,backlog指定最大排队数 |
accept() -> (conn, addr) | 接受连接,返回新socket对象和客户端地址 |
connect((ip,port)) | 客户端连接服务器 |
send()/recv() | 发送/接收数据 |
4.3 UDP专用方法
方法 | 说明 |
---|---|
sendto(data, address) | 发送数据到指定地址 |
recvfrom(bufsize) -> (data, addr) | 接收数据和发送方地址 |
五、IP 地址 & 端口号基础
- IP 地址:标识一台主机(例如
127.0.0.1
表示本地) - 端口号:标识主机上的某个程序,取值范围:
0~65535
范围 | 类型 |
---|---|
0 - 1023 |
系统端口 |
1024 - 49151 |
注册端口 |
49152 - 65535 |
动态端口 |
六、TCP 编程流程详解(面向连接)
🔹 1. 单次通信示例
TCP 服务器端
from socket import socket, AF_INET, SOCK_STREAM
server_socket = socket(AF_INET, SOCK_STREAM) # 1. 创建 socket
server_socket.bind(('127.0.0.1', 8888)) # 2. 绑定地址和端口
server_socket.listen(5) # 3. 开始监听
print('服务器启动,等待连接...')
client_socket, client_addr = server_socket.accept() # 4. 等待客户端连接
data = client_socket.recv(1024).decode('utf-8') # 5. 接收数据
print('收到客户端数据:', data)
client_socket.send('Hello from server!'.encode('utf-8')) # 6. 发送响应
client_socket.close()
server_socket.close()
TCP 客户端
import socket
client_socket = socket.socket()
client_socket.connect(('127.0.0.1', 8888)) # 连接服务器
print('连接成功')
client_socket.send('Welcome to Python'.encode('utf-8')) # 发送数据
client_socket.close()
🟡 注意:先运行服务器端,再运行客户端!
🔹 2. 多次通信示例(支持对话)
TCP 服务器端
from socket import socket, AF_INET, SOCK_STREAM
server_socket = socket(AF_INET, SOCK_STREAM)
server_socket.bind(('127.0.0.1', 8888))
server_socket.listen(5)
print('服务启动,等待连接...')
client_socket, _ = server_socket.accept()
data = client_socket.recv(1024).decode('utf-8')
while data != 'bye':
if data:
print('接收到客户端数据:', data)
send_data = input('回复客户端:')
client_socket.send(send_data.encode('utf-8'))
if send_data == 'bye':
break
data = client_socket.recv(1024).decode('utf-8')
client_socket.close()
server_socket.close()
TCP 客户端
import socket
client_socket = socket.socket()
client_socket.connect(('127.0.0.1', 8888))
print('已连接服务器')
info = ''
while info != 'bye':
msg = input('发送给服务器:')
client_socket.send(msg.encode('utf-8'))
if msg == 'bye':
break
info = client_socket.recv(1024).decode('utf-8')
print('服务器回复:', info)
client_socket.close()
七、UDP 编程流程详解(无连接)
🔹 1. 发送方代码
from socket import socket, AF_INET, SOCK_DGRAM
send_socket = socket(AF_INET, SOCK_DGRAM)
data = input('发送内容:')
send_socket.sendto(data.encode('utf-8'), ('127.0.0.1', 8888)) # 发送数据
recv_data, addr = send_socket.recvfrom(1024)
print('接收到回复:', recv_data.decode('utf-8'))
send_socket.close()
🔹 2. 接收方代码
from socket import socket, AF_INET, SOCK_DGRAM
recv_socket = socket(AF_INET, SOCK_DGRAM)
recv_socket.bind(('127.0.0.1', 8888)) # 绑定地址端口
recv_data, addr = recv_socket.recvfrom(1024)
print('收到数据:', recv_data.decode('utf-8'))
reply = input('回复:')
recv_socket.sendto(reply.encode('utf-8'), addr)
recv_socket.close()
🔹 模拟聊天场景
-
客户咨询者
# 客户咨询者
from socket import socket,AF_INET,SOCK_DGRAM
# (1)创建socket对象
send_socket=socket(AF_INET,SOCK_DGRAM)
while True:
# (2) 指定接收方IP地址和端口号
ip_port=('127.0.0.1',8888)
# (3) 准备发送数据
data=input('请输入要发送的数据:')
# (4) 发送数据
send_socket.sendto(data.encode('utf-8'),ip_port)
if data == 'bye':
break
# (5) 接收来自接客服的回复数据
recv_data,addr = send_socket.recvfrom(1024)
print('客服回复:',recv_data.decode('utf-8'))
# 关闭socket对象
send_socket.close()
-
客服人员
from socket import socket,AF_INET,SOCK_DGRAM
# (1) 使用socket类创建一个套接字对象
recv_socket=socket(AF_INET,SOCK_DGRAM)
# (2)绑定发送方IP和主机设置的端口号
ip = '127.0.0.1'
port = 8888
recv_socket.bind((ip,port))
while True:
# (3) 接收来自发送方的数据
recv_data,addr = recv_socket.recvfrom(1024)
print('客户说:',recv_data.decode('utf-8'))
if recv_data.decode('utf-8') == 'bye':
break
# (4) 准备回复对方的数据
data = input('回复:')
# (5) 回复:
recv_socket.sendto(data.encode('utf-8'),addr)
# (6) 结束
recv_socket.close()
🟡 注意:UDP编程接收方与发送方启动运行无先后,但先启动运行发送方,数据会丢包
八、总结
特性 | TCP | UDP |
---|---|---|
是否连接 | 需要连接(连接后通信) | 无需连接(直接发送数据) |
是否可靠 | 是,数据有序、无丢失 | 否,可能丢包、乱序 |
速度 | 相对较慢 | 快速 |
应用场景 | 文件传输、网页、聊天应用 | 视频直播、游戏、广播通知 |
Socket 的工作流程
Socket 的工作流程因协议不同而略有差异,以下是两种常见协议的典型流程:
-
TCP Socket 的工作流程
- 服务器端:
-
创建套接字:
socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-
绑定地址和端口:
socket.bind((host, port))
-
开始监听:
socket.listen()
-
接受连接:
socket.accept()
(返回一个新的套接字和客户端地址) -
通信:通过返回的套接字发送和接收数据
-
关闭连接:
socket.close()
-
- 客户端:
-
创建套接字:
socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-
连接到服务器:
socket.connect((host, port))
-
通信:发送和接收数据
-
关闭连接:
socket.close()
-
- 服务器端:
-
UDP Socket 的工作流程
- 服务器端:
-
创建套接字:
socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-
绑定地址和端口:
socket.bind((host, port))
-
接收数据:
socket.recvfrom(buffer_size)
(返回数据和客户端地址) -
发送数据:
socket.sendto(data, address)
-
关闭套接字:
socket.close()
-
- 客户端:
-
创建套接字:
socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-
发送数据:
socket.sendto(data, address)
-
接收数据:
socket.recvfrom(buffer_size)
-
关闭套接字:
socket.close()
-
- 服务器端: