socketserver模块
一般情况下,所有的服务,都是先建立连接,也就是建立一个服务类的实例,然后开始处理用户请求,也就是建立一个请求处理类的实例。
我们分析一下源码,来看一看服务类是如何与请求处理类建立联系的。
class BaseServer:#我们创建服务类时,需要指定(地址,端口),服务处理类。
def __init__(self, server_address, RequestHandlerClass):
"""Constructor. May be extended, do not override."""
self.server_address = server_address
self.RequestHandlerClass = RequestHandlerClass
self.__is_shut_down = threading.Event()
self.__shutdown_request = False
#…………此处省略n多代码,当我们执行server_forever方法时,里面就会调用很多服务类中的其他方法,但最终会调用finish_request方法。
def finish_request(self, request, client_address):
"""Finish one request by instantiating RequestHandlerClass."""
self.RequestHandlerClass(request, client_address, self)
#finish_request方法中执行了self.RequestHandlerClass(request, client_address, self)。self.RequestHandlerClass是什么呢?#self.RequestHandlerClass = RequestHandlerClass(就在__init__方法中)。所以finish_request方法本质上就是创建了一个服务处理实例。
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()#当我们创建服务处理类实例时,就会运行handle()方法,而handle()方法则一般是我们处理事务逻辑的代码块。
#…………此处省略n多代码
TCPServer针对TCP套接字流
UDPServer针对UDP数据报套接字
UnixStreamServer和UnixDatagramServer针对UNIX域套接字,不常用。
他们之间的继承关系:

要实现一项服务,还必须派生一个handler class请求处理类,并重写父类的handle()方法。handle方法就是用来专门是处理请求的。该模块是通过服务类和请求处理类组合来处理请求的。
SocketServer模块提供的请求处理类有BaseRequestHandler,以及它的派生类StreamRequestHandler和DatagramRequestHandler。从名字看出可以一个处理流式套接字,一个处理数据报套接字。
请求处理类有三种方法:
setup()
Called before the handle() method to perform any initialization actions required. The default implementation does nothing.
也就是在handle()之前被调用,主要的作用就是执行处理请求之前的初始化相关的各种工作。默认不会做任何事。(如果想要让其做一些事的话,就要程序员在自己的请求处理器中覆盖这个方法(因为一般自定义的请求处理器都要继承python中提供的BaseRequestHandler,ps:下文会提到的),然后往里面添加东西即可)
handle()
This function must do all the work required to service a request. The default implementation does nothing. Several instance attributes are available to it; the request is available as self.request; the client address as self.client_address; and the server instance as self.server, in case it needs access to per-server information.
The type of self.request is different for datagram or stream services. For stream services,self.request is a socket object; for datagram services, self.request is a pair of string and socket.
handle()的工作就是做那些所有与处理请求相关的工作。默认也不会做任何事。他有数个实例参数:self.request self.client_address self.server
finish()
Called after the handle() method to perform any clean-up actions required. The default implementation does nothing. If setup() raises an exception, this function will not be called.
在handle()方法之后会被调用,他的作用就是执行当处理完请求后的清理工作,默认不会做任何事
服务端
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
try:
while True:
self.data=self.request.recv(1024)
print("{} send:".format(self.client_address),self.data)
if not self.data:
print("connection lost")
break
self.request.sendall(self.data.upper())
except Exception as e:
print(self.client_address,"连接断开")
finally:
self.request.close()
def setup(self):
print("before handle,连接建立:",self.client_address)
def finish(self):
print("finish run after handle")
if __name__=="__main__":
HOST,PORT = "localhost",9988
server=socketserver.TCPServer((HOST,PORT),MyTCPHandler)
server.serve_forever()
客户端
import socket
client=socket.socket()
client.connect(('localhost',9988))
while True:
cmd=input("(quit退出)>>").strip()
if len(cmd)==0:
continue
if cmd=="quit":
break
client.send(cmd.encode())
cmd_res=client.recv(1024)
print(cmd_res.decode())
client.close()
异步处理
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
try:
while True:
self.data=self.request.recv(1024)
print("{} send:".format(self.client_address),self.data)
if not self.data:
print("connection lost")
break
self.request.sendall(self.data.upper())
except Exception as e:
print(self.client_address,"连接断开")
finally:
self.request.close()
def setup(self):
print("before handle,连接建立:",self.client_address)
def finish(self):
print("finish run after handle")
HOST,PORT = "localhost",9999
server=socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler)#多线程版
server.serve_forever()
天道酬勤 循序渐进 技压群雄
浙公网安备 33010602011771号