这两段代码展示了如何使用 Python 的 socket 和 multiprocessing 模块来实现一个简单的客户端-服务器通信系统。以下是对每段代码的详细解释:
代码段 1:服务器端(使用 multiprocessing 进行进程间通信)
import time
from multiprocessing import Queue, Process
import socket
def receive_data(q):
# 创建socket对象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 获取本机IP地址
ip = socket.gethostbyname(socket.gethostname())
port = 12345
# 绑定IP地址和端口
s.bind((ip, port))
# 开始监听
s.listen()
print("等待连接...")
while True:
# 接受连接
conn, addr = s.accept()
print("连接成功!")
# 接收数据
while True:
chunk = conn.recv(1024).decode()
if not chunk:
break
q.put(chunk)
q.put(None) # 使用 None 作为数据接收结束的标志
conn.close()
def read_data(q):
print("开始读取数据...")
while True:
data = q.get()
if data is None:
# 数据接收完成
break
print("读取到数据:", data)
time.sleep(3)
if __name__ == '__main__':
q = Queue()
receiver = Process(target=receive_data, args=(q,))
qr = Process(target=read_data, args=(q,))
receiver.start()
qr.start()
qr.join() # 确保读取进程在接收进程完成后再退出
receiver.join()
解释
1.receive_data 函数
- 创建 Socket:socket.socket(socket.AF_INET,socket.SOCK_STREAM)
创建一个 TCP/IP 套接字。 - 绑定和监听:将套接字绑定到本机 IP 地址和端口 12345,并开始监听传入的连接。
- 接收数据:接受连接后,不断从连接中读取数据,每次读取的数据放入 Queue 对象 q 中。数据读取完成后,关闭连接。
2.read_data 函数:
- 读取数据:从 Queue 中读取数据并打印。每次读取数据后,程序暂停 3 秒。这个函数会在队列为空时退出循环。
3.主程序:
- 创建进程:创建两个进程,一个用于接收数据(receive_data),另一个用于读取数据(read_data)。
- 启动和等待进程:启动两个进程,并使用 join() 等待它们完成。
代码段 2:客户端(发送数据到服务器)
import socket
import time
def send_data(server_ip, server_port):
try:
# 创建socket对象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 连接到服务器
s.connect((server_ip, server_port))
while True:
alphabet = 'abcdefghijklmnopqrstuvwxyz'
# 每次发送的字母数
chunk_size = 5
for i in range(0, len(alphabet), chunk_size):
# 获取当前要发送的字母
chunk = alphabet[i:i + chunk_size]
print(f"发送: {chunk}")
# 发送字母
s.send(chunk.encode('utf-8'))
# 等待一段时间,模拟发送间隔
time.sleep(1) # 减少等待时间以更快地发送数据
# 发送完毕,关闭连接
s.close()
except ConnectionAbortedError as e:
print(f"连接中断错误: {e}")
except ConnectionRefusedError as e:
print(f"连接被拒绝错误: {e}")
except Exception as e:
print(f"发生了其他错误: {e}")
finally:
# 确保连接被关闭
s.close()
if __name__ == '__main__':
# 服务器IP和端口号
server_ip = socket.gethostbyname(socket.gethostname()) # 替换为实际服务器的IP地址
server_port = 12345 # 端口号应与接收端一致
send_data(server_ip, server_port)
解释
1.send_data 函数:
- 创建 Socket:创建一个 TCP/IP 套接字。
- 连接服务器:连接到指定的服务器 IP 和端口。
- 发送数据:循环发送字母表中的数据,每次发送 5 个字母,然后暂停 1 秒。这是为了模拟数据发送间隔。
- 关闭连接:发送数据完成后,关闭套接字连接。捕获和处理可能出现的连接错误。
2.主程序:
- 获取服务器 IP 和端口:使用本机 IP 地址和端口号 12345 进行连接。确保这些信息与服务器端匹配。
- 调用发送函数:调用 send_data 函数,开始发送数据到服务器。
总结
- 服务器端:监听特定端口上的连接,接收客户端发送的数据,将其存储到一个消息队列中,并从队列中读取和处理这些数据。
- 客户端:连接到服务器,并不断发送数据到指定的 IP 和端口。
这个系统允许服务器端和客户端之间进行简单的 TCP/IP 通信,并且服务器端使用多进程来处理数据接收和读取。