4、使用socket通信(创建TCP服务端和客户端)并加入多线程
需求:
- 服务端
- 收到客户端连接后输出客户端地址信息
- 可同时连接多个客户端
- 收到客户端发送的数据后,将数据发送给所有连接的客户端
- 客户端:
- 获取用户输入后,将输入数据发送给服务端
- 打印服务端返回的数据
- 用户可多次输入
解决方案:
- 使用socket通信
- 发送数据:send() 方法用于 TCP 协议的通信;sendto() 方法用于 UDP 协议的通信
- 接受数据:recv() 方法
- 加入多线程
- 通过 threading.Thread 创建线程
- 服务端为每个客户端启动一条线程(保证各客户端互不干扰)
- 客户端为网络 IO 启动一条线程,为用户交互启动一条线程
服务端:
import socket, threading
client_list = [] # 客户端列表
def server_target(sever_socket):
while True:
content = sever_socket.recv(2048).decode('UTF-8') # 接受客户端发送的数据
if content is not None:
print(content) # 打印客户端发送的数据
for cl in client_list: # 将数据送回给每个客户端
cl.send(content.encode('UTF-8'))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
s.bind(('192.168.1.10', 30000))
s.listen()
while True:
c, addr = s.accept()
print(addr)
client_list.append(c) # 将所有客户端对应的socket保存在列表中
threading.Thread(target=server_target, args=(c,)).start() # 为客户端对应的socket启动对应的线程
客户端:
import socket, threading
def read_server(client_socket):
while True:
content = client_socket.recv(2048).decode('UTF-8')
if content is not None:
print(content)
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('192.168.1.10', 30000))
# 将 read_socket 函数以多线程的方式启动,这样该函数(包含死循环)能与下面的死循环并发执行
threading.Thread(target=read_server, args=(client_socket,)).start()
while True:
line = input('') # 获取用户输入
if line is None or line == 'exit':
break
client_socket.send(line.encode('UTF-8')) # 将用户输入的内容发送给服务端
步骤:
-
运行服务端
-
运行 3 个客户端后,服务端界面:
-
客户端 1 输入:客户端1测试1
服务端界面 客户端2界面 客户端3界面 -
客户端1输入:客户端1测试2
服务端界面 客户端2界面 客户端3界面 -
其它客户端同理