SocketServer功能:实现并发处理,就是将socket在封装,使得遍的更简单。
类型:
#TCPserver:TCP的socketserver。
class socketserver.TCPServer(server_address,RequestHandlerClass, bind_and_activate=True)
#UDPserver:UDP的socketserver。
class socketserver.UDPServer(server_address, RequestHandlerClass, bind_and_activate=True)
#UnixStreamServer:本级之间TCP不同进程时使用。
class socketserver.UnixStreamServer(server_address, RequestHandlerClass, bind_and_activate=True)
#UnixDatagramServer:本级之间UDP不同进程时使用。
class socketserver.UnixDatagramServer(server_address, RequestHandlerClass,bind_and_activate=True)
上述每个类型都继承了一个基类,最终都是BaseServer类:
+------------+
| BaseServer |
+------------+
|
v
+-----------+ +------------------+
| TCPServer |------->| UnixStreamServer |
+-----------+ +------------------+
|
v
+-----------+ +--------------------+
| UDPServer |------->| UnixDatagramServer |
+-----------+ +--------------------+
创建一个socketserver
1.创建一个请求处理类,并且这个类要继承BaseRequestHandler,并且还要重写父类里的handle()方法。
2.实例化一个TCPserver(soketServer类型)并且传递server ip 和上面创建的请求处理类,给这个TCPserver。
3.server.handle_request() #只处理一个请求,退出server.server_forever() #处理多个请求,永远执行
4.调用server_close()关闭server。
注:handle()方法:与客户端所有的交互都是handle里完成的。
注:MyTCPHandler()请求类:每次客户端请求都会实例化。
#添加socketserver模块
import socketserver
#处理请求类,继承BaseRequestHandler
class MyTCPHandler(socketserver.BaseRequestHandler):
#重写父类的handle方法
def handle(self):
#循环处理Client请求
while True:
#客户端断开后会报ConnectionResetError错误
try:
#接收客户端send,写法self.request.recv()
self.data = self.request.recv(1024).strip()
#打印链接Client的IP地址
print("{} wrote:".format(self.client_address[0]))
#打印Client请求数据
print(self.data)
#处理并发回处理请求,写法self.request.send()
self.request.send(self.data.upper())
#Client断开报错处理,赋值e
except ConnectionResetError as e:
print("err",e)
break
if __name__ == "__main__":
#创建服务端IP,端口
HOST, PORT = "localhost", 9999
#ForkingTCPServer:多进程,Linux可用,windows(没有os.fork(创建新进程)不可用)。
#ThreadingTCPServer:多线程,效果相同。
#实例化ThreadingTCPServer:一对多并发处理,每多一位Client多开一个独立线程。
server = socketserver.ThreadingTCPServer((HOST, PORT),MyTCPHandler)
#实例化TCPServer:一对一的请求处理。
#server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
#执行服务端
server.serve_forever()
class socketserver.BaseServer(server_address, RequestHandlerClass)
#这是模块中所有服务器对象的超类。它定义了下面给出的接口,但是并没有实现大多数方法,这些方法都是在子类中完成的。这两个参数存储在各自的server_address和RequestHandlerClass属性中。
fileno()
#返回服务器正在监听的套接字的整数文件描述符。这个函数通常被传递给选择器,以便在相同的进程中监视多个服务器。
handle_request()
#处理一个请求。该函数调用以下方法:get_request()、verify_request()和process_request()。如果处理程序类的用户提供的handle()方法引发异常,则调用服务器的handle_error()方法。如果在超时时间内没有收到请求,将调用handle_timeout()并返回handle_request()。
serve_forever(poll_interval=0.5)
#处理请求,直到显式关闭()请求。轮询关闭每个poll_interval秒。忽略了超时属性。它还调用service_actions(),它可以被子类或mixin使用,以提供特定于给定服务的操作。例如,ForkingMixIn类使用service_actions()来清理僵尸进程。
service_actions()
#这在serve_forever()循环中调用。该方法可以被子类或mixin类覆盖,以执行特定于给定服务的操作,例如清理操作。
shutdown()
#告诉serve_forever()循环停止并等待直到它完成。
server_close()
#清理服务器。可能会被覆盖。
address_family
#服务器套接字所属的协议族。常见的例子是套接字。AF_INET socket.AF_UNIX。
RequestHandlerClass
#用户提供的请求处理程序类;为每个请求创建该类的一个实例。
server_address
#服务器正在监听的地址。地址的格式取决于协议族;详细信息请参阅套接字模块的文档。对于Internet协议,这是一个包含给出地址的字符串的元组,以及一个整数端口号(例如:“127.0.0.1”,80)。
allow_reuse_address
#服务器是否允许重用地址。此缺省值为False,可以在子类中设置更改策略。
request_queue_size
#请求队列的大小。如果需要很长时间来处理单个请求,当服务器繁忙时到达的任何请求都被放置到队列中,直到request_queue_size请求。一旦队列满了,来自客户端的进一步请求将会得到一个“拒绝连接”错误。默认值通常是5,但这可以被子类覆盖。
socket_type
#服务器使用的套接字的类型;套接字。SOCK_STREAM套接字。SOCK_DGRAM是两个常见的值。
#超时时间,以秒为单位,如果不需要超时,则为零。如果handle_request()在超时时间内没有收到传入请求,则调用handle_timeout()方法。
finish_request()
#实际上,通过实例化RequestHandlerClass并调用它的handle()方法来处理请求。
get_request()
#必须接受来自套接字的请求,并返回一个包含新套接字对象的2元组,用于与客户端进行通信,以及客户端的地址。
client_address handle_error(请求)
#如果RequestHandlerClass实例的handle()方法引发异常,则调用此函数。默认的操作是将traceback打印到标准输出,并继续处理进一步的请求。
handle_timeout()
#当超时属性被设置为其他值时,该函数被调用,超时时间已经过去,没有收到任何请求。forking服务器的默认动作是收集已退出的任何子进程的状态,而在线程服务器中,此方法什么都不做。
client_address process_request(请求)
#调用finish_request()来创建RequestHandlerClass的实例。如果需要,这个函数可以创建一个新的进程或线程来处理请求;ForkingMixIn和ThreadingMixIn类这样做。
server_activate()
#由服务器的构造函数调用来激活服务器。TCP服务器的默认行为只是在服务器的套接字上调用listen()。可能会被覆盖。
server_bind()
#由服务器的构造函数调用,以将套接字绑定到所需的地址。可能会被覆盖。
client_address verify_request(请求)
#必须返回一个布尔值;如果值为真,请求将被处理,如果是错误的,请求将被拒绝。可以重写此函数来实现服务器的访问控制。默认的实现总是返回True
test