基于socket建立多线程的服务端与客户端通信
这边有一个服务端两个客户端
目录1234的代码都是在web_server.py里,connector_1.py与connector_2.py内容一样
一、搭建网络模型
from socket import *
from multiprocessing import Process
"""
基于多进程的网络并发模型
"""
class WebSocketServer:
def __init__(self, host="127.0.0.1", port=8005):
self.socket = socket()
self.host = host
self.port = port
def bind(self):
"""监听套接字"""
self.socket.bind((self.host, self.port))
self.socket.listen() # 设置监听套接字
def bind_connection(self):
"""建立连接"""
while True:
print("等待连接....")
conn, addr = self.socket.accept() # 连接
print(f"连接到:{addr[0]}\t端口:{addr[1]}")
return conn, addr
def close(self):
""" 关闭监听套接字"""
self.socket.close()
首先,建立服务端。需要服务端的host和port。这边是用创建对象的方式建立。因为项目上多用。
socket的网络搭建步骤是:
1.创建socket对象
2.设置监听套接字
3.建立连接(连接到一个客户端后会获取到连接对象和连接地址)
4.关闭连接
二、创建连接对象
class Connection:
def __init__(self, conn, addr):
self.conn = conn
self.addr = addr
def close(self):
"""断开连接"""
self.conn.close()
print(f"{self.addr[0]}:{self.addr[1]}断开连接")
def send_msg(self, message):
"""发送信息"""
self.conn.send(message.encode())
def receive_msg(self, bufsize=1024):
"""接受信息"""
data_received = self.conn.recv(bufsize).decode()
return data_received
创建连接的对象,可以方便处理每一个连接过来的客户端。基础的接受与发送消息。
三、循环处理连接
def handle(conn, addr):
"""循环处理连接"""
connection = Connection(conn, addr) # 创建客户端连接对象
while True:
data = connection.receive_msg() # 持续获取该对象信息
if data:
print(f"{connection.addr[0]}:{connection.addr[1]}:{data}")
if data == "##": # 创建一个与单个客户端断开连接的方式
connection.send_msg("##")
connection.close()
break
try: # 返回消息
msg = eval(data)
connection.send_msg(str(msg))
except:
msg = "输入有误!请重新输入。"
connection.send_msg(str(msg))
客户端的连接可能是持续的或者循环的。
对于每一个连接的客户端,我们对其创建一个连接对象。然后用多进程的方式处理单个连接对象。
四、多进程连接网络
if __name__ == '__main__':
webserver = WebSocketServer()
webserver.bind() # 服务端启动
while True:
conn, addr = webserver.bind_connection() # 获取每个连接客户端
p = Process(target=handle, args=(conn, addr), daemon=True) # 多进程循环处理连接
p.start()
五、构建客户端
from socket import *
tcp_socket = socket()
tcp_socket.connect(("127.0.0.1", 8005)) # 需要连接的服务端
while True:
msg = input(">>")
if not msg:
break
tcp_socket.send(msg.encode())
data = tcp_socket.recv(1024).decode()
if data == "##":
print("服务端关闭连接")
break
print(data)
tcp_socket.close()
效果如下:
先开启服务端,再开启两个客户端