15.3. socketserver编程¶
socketserver在内部使用IO多路复用以及多线程/进程机制,实现了并发处理多个客户端请求的socket服务端。每个客户端请求连接到服务器时,socketserver服务端都会创建一个“线程”或者“进程” 专门负责处理当前客户端的所有请求。
socketserver模块中使用的服务器类主要有:
TCPServer #TCP协议的服务类
UDPServer #TCP协议的服务类
ThreadingTCPServer #多线程服务器类
ThreadingUDPServer
ForkingTCPServer #多进程服务器类
ForkingUDPServer
15.3.1. 使用ThreadingTCPServer的要点:¶
创建一个继承自socketserver.BaseRequestHandler的类;
这个类中必须定义一个名字为handle的方法,不能是别的名字!
将这个类,连同服务器的ip和端口,作为参数传递给ThreadingTCPServer()构造器
手动启动ThreadingTCPServer。
15.3.2. ThreadingTCPServer 示例¶
服务端 1¶
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socketserver
class MyServer(socketserver.BaseRequestHandler):
"""
必须继承socketserver.BaseRequestHandler类
"""
def handle(self):
"""
必须实现这个方法!
:return:
"""
conn = self.request # request里封装了所有请求的数据
conn.sendall('欢迎访问socketserver服务器!'.encode())
while True:
data = conn.recv(1024).decode()
if data == "exit":
print("断开与%s的连接!" % (self.client_address,))
break
print("来自%s的客户端向你发来信息:%s" % (self.client_address, data))
conn.sendall(('已收到你的消息<%s>' % data).encode())
if __name__ == '__main__':
# 创建一个多线程TCP服务器
server = socketserver.ThreadingTCPServer(('127.0.0.1', 9999), MyServer)
print("启动socketserver服务器!")
# 启动服务器,服务器将一直保持运行状态
server.serve_forever()
服务器 2¶
#!/usr/bin/env python
#-*- coding:utf8 -*-
'''
TCPServer
UDPServer
ThreadingTCPServer
ThreadingUDPServer
socketserver模块中使用的处理器类主要有StreamRequestHandler(基于TCP协议的)和DatagramRequestHandler(基于UDP协议的)
三个方法:
setup() #为请求准备请求处理器(请求处理的初始化工作)
handler() #完成具体的请求处理工作(解析请求、处理数据、发出响应)
finish() #清理请求处理器相关数据
一般,自定义一个简单的请求处理器,只需覆盖handler()方法即可
'''
import socketserver
HOST = "localhost"
PORT = 10888
class MyTcpHandler(socketserver.StreamRequestHandler):
'''
定义了一个继承自StreamRequestHandler的处理器类,覆盖了handler()方法
然后实例化TCPServer类,调用serve_forever()方法启动服务器
'''
def handle(self):
while True:
data = self.request.recv(1024)
if not data:
Server.shutdown()
break
print("Receive Data:", data.decode('utf-8'))
self.request.send(data)
return
Server = socketserver.TCPServer((HOST,PORT),MyTcpHandler)
Server.serve_forever()
客户端¶
客户端和socket一样,保持不变
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
客户端依然使用socket模块就可以了,不需要导入socketserver模块
"""
import socket
ip_port = ('127.0.0.1', 9999)
sk = socket.socket()
sk.connect(ip_port)
sk.settimeout(5)
data = sk.recv(1024).decode()
print('服务器:', data)
while True:
inp = input('你:').strip()
if not inp:
continue
sk.sendall(inp.encode())
if inp == 'exit':
print("谢谢使用,再见!")
break
data = sk.recv(1024).decode()
print('服务器:', data)
sk.close()
15.3.3. 服务器端的代码,核心要点¶
连接数据封装在self.request中!调用send()和recv()方法都是通过self.request对象。
handle()方法是整个通信的处理核心,一旦它运行结束,当前连接也就断开了(但其他的线程和客户端还正常),因此一般在此设置一个无限循环。
注意server = socketServer.ThreadingTCPServer((‘127.0.0.1’,8009),MyServer)中参数传递的方法。
server.serve_forever()表示该服务器在正常情况下将永远运行。 socketserver模块还提供了ThreadingUDPServer类,用于提供多线程的UDP服务。还有ForkingTCPServer类,当操作系统支持fork操作的时候,可以实现多进程服务器。他们的用法和ThreadingTCPServer基本类似