类的继承
SocketServer简化了网络服务器的编写
它有4个同步类:
- TCPServer
- UDPServer
- UnixStreamServer
- UnixDatagramServer
2个Mixin类:ForkingMixin和ThreadingMixin类,用来支持异步。
- class ForkingUDPServer(ForkingMixin,UDPServer): pass
- class ForkingTCPServer(ForkingMixin,UDPServer):pass
- class ThreadingUDPServer(ThreadingMixin,UDPServer): pass
- class ThreadingTCPServer(ThreadingMixin,TCPServer): pass
fork是创建多进程,thread是创建多线程。
fork需要操作系统支持,windows不支持
编程接口
socketserver.BaseServer(server_address, RequestHandlerClass)
需要提供服务器绑定的地址信息,和用于处理请求的RequestHandlerClass类。
RequestHandlerClass类必须是BaseRequestHandler类的子类.
BaseRequestHandler类
它是和用户连接的用户请求处理类的基类,定义为
BaseRequestHandler(request, client_address, server)
服务端Server实例接收用户请求后,最后会实例化这个类。
它被初始化时,送入三个构造参数:request,client_address,server自身
以后就可以在BaseRequestHandler类的实例上使用以下属性:
- self.request是和客户端的连接的socket对象
- self.server是TCPServer实例本身
- self.client_address是客户端地址
这个类在初始化的时候,会依次调用三个方法,子类可以覆盖这些方法。
# BaseRequestHandler要子类覆盖的方法
class BaseRequestHandler:
def __init__(self, request, client_address, server):
self.request = request
self.client_address = client_address
self.server = server
self.setup()
try:
self.handle()
finally:
self.finish()
def setup(self): # 每一个连接初始化
pass
def handle(self): # 每一次请求处理
pass
def finish(self): # 每一个连接清理
pass
import socketserver
import threading
class MyHandler(socketserver.BaseRequestHandler):
def handle(self):
super().handle()
print(self.server) #服务
print(self.request) #服务端负责客户端连接请求的socket对象
print(self.client_address)#客户端地址
print(self.__dict__)
print(self.server.__dict__)# 能看到负责accept的socket
print(threading.enumerate())
print(threading.current_thread())
addr=('127.0.0.1',9999)
server=socketserver.ThreadingTCPServer(addr,MyHandler)
server.serve_forever()
测试结果说明,handle方法相当于socket的recv方法
每个不同的连接上的请求过来后,生成这个连接的socket对象即self.request,客户端地址是self.client_address
import socketserver
import threading
class MyHandler(socketserver.BaseRequestHandler):
def handle(self):
super().handle()
print(self.server) #服务
print(self.request) #服务端负责客户端连接请求的socket对象
print(self.client_address)#客户端地址
print(self.__dict__)
print(self.server.__dict__)# 能看到负责accept的socket
print(threading.enumerate())
print(threading.current_thread())
for i in range(3):
data=self.request.recv(1024)
print(data)
return 1
addr=('127.0.0.1',9999)
server=socketserver.TCPServer(addr,MyHandler)
server.serve_forever() #永久启用
将ThreadingTCPServer换成TCPServer,同时连接2个客户端观察结果。
ThreadingTCPSever是异步的,可以同时处理多个连接。
TCPServer是同步的,一个连接处理完了,即一个连接的handle方法执行完了,才能处理另一个连接,且只有主线程。
总结
创建服务器需要以下几个步骤
- 从BaseRequestHandler类派生出子类,并覆盖其handle()方法来创建请求处理程序类,此方法将处理传入请求
- 实例化一个服务器类,传参服务器的地址和请求处理类
- 调用服务器实例的handle_request()或serve_forsever()方法
- 调用server_close()关闭套接字