socketserver模块
先来看个例子,最简单的服务端与客户端的聊天小程序。这个小程序只能实现一对一的聊天。
服务端:
# 服务端
import socket
address = ("127.0.0.1", 9090)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(address)
server.listen(5)
while True:
print("等待连接...")
conn, addr = server.accept()
print("addr: %s 已连接" % (addr,))
while True:
try:
recv_data = conn.recv(1024).decode("utf-8")
if not recv_data: break
print("收到客户端信息:", recv_data)
if recv_data == "exit":
print("addr: %s 连接已断开" % (addr,))
break
while True:
send_data = input("我:").strip()
if not send_data: continue
if send_data == "exit":
conn.send(send_data.encode("utf-8"))
raise ConnectionResetError
conn.send(send_data.encode("utf-8"))
break
except ConnectionResetError:
print("addr: %s 连接已断开" % (addr,))
break
conn.close()
server.close()
客户端:
# 客户端
import socket
address = ("127.0.0.1", 9090)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(address)
while True:
inp = input(">>:").strip()
if not inp: continue
client.send(inp.encode("utf-8"))
if inp == "exit": break
recv_data = client.recv(1024).decode("utf-8")
print("来自服务端消息:", recv_data)
if recv_data == "exit":
print("服务端主动断开,再见。")
break
client.close()
运行如下:
服务端:
等待连接... addr: ('127.0.0.1', 6982) 已连接 收到客户端信息: 你好 我:有啥事 收到客户端信息: 没事 我:exit addr: ('127.0.0.1', 6982) 连接已断开 等待连接...
客户端:
>>:你好 来自服务端消息: 有啥事 >>:没事 来自服务端消息: exit 服务端主动断开,再见。
这个小程序只能实现一对一的聊天,并不能实现多个客户端同时聊天,要想实现和多个客户端同时聊天需要使用到多线程。
多线程版:
只需要稍微改动即可:
服务器端:
# 服务端
import socket
from threading import Thread
address = ("127.0.0.1", 9090)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(address)
server.listen(5)
def tongxin(conn):
while True:
try:
recv_data = conn.recv(1024).decode("utf-8")
if not recv_data: break
print("收到客户端 %s 的信息: %s " % (addr, recv_data))
if recv_data == "exit":
print("addr: %s 连接已断开" % (addr,))
break
while True:
send_data = input("我:").strip()
if not send_data: continue
if send_data == "exit":
conn.send(send_data.encode("utf-8"))
raise ConnectionResetError
conn.send(send_data.encode("utf-8"))
break
except ConnectionResetError:
print("addr: %s 连接已断开" % (addr,))
break
conn.close()
while True:
print("等待连接...")
conn, addr = server.accept()
print("addr: %s 已连接" % (addr,))
t = Thread(target=tongxin, args=(conn,))
t.start()
server.close()
客户端不变:
# 客户端
import socket
address = ("127.0.0.1", 9090)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(address)
while True:
inp = input(">>:").strip()
if not inp: continue
client.send(inp.encode("utf-8"))
if inp == "exit": break
recv_data = client.recv(1024).decode("utf-8")
print("来自服务端消息:", recv_data)
if recv_data == "exit":
print("服务端主动断开,再见。")
break
client.close()
这样即可实现多个客户端都能够向服务器端发送消息,并可以得到回复。
从上面例子其实可以看出,我们每次在写网络编程相关的code的时候都需要必写的三句code:
address = ("127.0.0.1", 9090) server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind(address) server.listen(5)
其实有一个socketserver模块已经帮我们封装好了这些操作,并且开启多线程的操作也封装进去了,下面我们就使用socketserver模块来改造一下:
服务器端:
# 服务端
import socketserver # 导入socketserver模块
class MyServer(socketserver.BaseRequestHandler): # 必须继承BaseRequestHandler
def handle(self): # 固定写法,必须有一个handle方法,将要实现的功能模块放在里面
while True:
try:
recv_data = self.request.recv(1024).decode("utf-8") # 将原来的conn改为了 self.request
if not recv_data: break
print("收到客户端 %s 的信息: %s " % (self.client_address, recv_data)) # addr改为了self.client_address
if recv_data == "exit":
print("addr: %s 连接已断开" % (self.client_address,))
break
while True:
send_data = input("我:").strip()
if not send_data: continue
if send_data == "exit":
self.request.send(send_data.encode("utf-8"))
raise ConnectionResetError
self.request.send(send_data.encode("utf-8"))
break
except ConnectionResetError:
print("addr: %s 连接已断开" % (self.client_address,))
break
self.request.close()
server = socketserver.ThreadingTCPServer(("127.0.0.1", 9090), MyServer) # 固定写法
server.serve_forever() # 固定写法
客户端不变:
# 客户端
import socket
address = ("127.0.0.1", 9090)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(address)
while True:
inp = input(">>:").strip()
if not inp: continue
client.send(inp.encode("utf-8"))
if inp == "exit": break
recv_data = client.recv(1024).decode("utf-8")
print("来自服务端消息:", recv_data)
if recv_data == "exit":
print("服务端主动断开,再见。")
break
client.close()
运行结果和多线程一样。
更多资料请参考:https://www.cnblogs.com/yuanchenqi/articles/9534816.html
共有 0 条评论