socketserver
socketserver模块有四种基本的服务器类型:
- socketserver.TCPServer(server_address,RequestHandlerClass,bind_and_activate=True)
这使用了网络TCP协议,它提供了客户机和服务器之间的连续数据流。如果bind_and_activate是真的,构造函数会自动尝试调用server_bind()和server_activate()。其他参数传递给BaseServer基类。 - class socketserver.UDPServer(server_address, RequestHandlerClass, bind_and_activate=True)
它使用网络UDP协议,它是在传输过程中可能出现故障或丢失信息的离散信息包。参数与TCPServer相同。 - class socketserver.UnixStreamServer(server_address, RequestHandlerClass, bind_and_activate=True)¶
- class socketserver.UnixDatagramServer(server_address, RequestHandlerClass, bind_and_activate=True)¶
创建服务器需要几个步骤。
首先,您必须通过子类化BaseRequestHandler类并覆盖它的handle()方法来创建一个请求处理程序类;此方法将处理传入的请求。
其次,您必须实例化一个服务器类,将其传递给服务器的地址和请求处理程序类。
最后调用server_close()来关闭套接字,除非使用with
class socketserver.ForkingMixIn
class socketserver.ThreadingMinxIn
可以使用这些mix-in类创建每个类型的服务器的Forking和threading版本
1 | class ThreadingUDPServer(ThreadingMixIn, UDPServer): |
2 | pass |
下面提到的ForkingMixIn和Forking类只在支持fork()的POSIX平台上可用,这些类是使用mix-in类预先定义的。:
class socketserver.ForkingTCPServer
class socketserver.ForkingUDPServer
class socketserver.ThreadingTCPServer
class socketserver.ThreadingUDPServer
Request Handler对象
class sockerserver.BaseRequestHandler:
这是所有请求处理程序对象的超类,定义下面的接口,一个具体的请求处理程序子类必须定义一个新的handle()方法。
- setup()
在调用handle()方法前进行初始化操作,默认无任何操作 - handle()
此函数必须完成服务请求所需的所有工作,self.request:请求到达,self.client_address:客户端地址,self.server:服务器实例,datagram和stream服务的self.request是不同的。stream服务,self.request是一个套接字对象,datagram服务,self.request是一对字符和套接字 - finish()
调用handle()对象后清理工作需要,如果setup抛出异常,这个函数将不会被执行。
class socketserver.StreamRequestHandler
class sockerserver.DatagramRequestHandler
这些BaseRequestHandler的子类覆盖了setup()和finish()方式,并且提供了self.rfile和self.wfile属性,这些属性可以得到请求数据并且返回数据
Server对象
class socketserver.BaseServer(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)
处理请求直到shutdown()请求,每poll_interval轮询。 - service_actions()
这在serve_forever()循环中调用。该方法可以被子类或mixin类覆盖,以执行特定于给定服务的操作,例如清理操作。 - shutdown()
告诉serve_forever()循环停止并等待直到它完成。 - server_close()
清理服务器 - finish_request(request,client_address)
通过实例化RequestHandlerClass并调用它的handle()方法来处理请求。 - get_request()
必须接受来自套接字的请求,并返回一个包含新套接字对象的2元组,用于与客户端进行通信,以及客户端的地址。 - handle_error(request, client_address)
如果RequestHandlerClass实例的handle()方法引发异常,则调用此函数。默认的操作是将traceback打印到标准错误并继续处理进一步的请求。 - handle_timeout()
当超时属性被设置为一个值以外的值时,这个函数被调用,并且超时时间已经过去,没有收到任何请求。forking服务器的默认操作是收集已经退出的任何子进程的状态,而在线程服务器中,此方法什么也不做。 - process_request(request, client_address)
调用finish_request()来创建RequestHandlerClass的实例。如果需要,这个函数可以创建一个新的进程或线程来处理请求;ForkingMixIn和ThreadingMixIn类是这样做的。 - server_activate()
由服务器的构造函数调用来激活服务器。TCP服务器的默认行为只在服务器的套接字上调用listen()。 - server_bind()
由服务器的构造函数调用,以将套接字绑定到所需的地址。可能会被覆盖。 - verify_request(request, client_address)
必须返回一个布尔值;如果值为True,请求将被处理,如果是False,请求将被拒绝。可以重写此函数来实现服务器的访问控制。默认实现总是返回True。
sockerserver.TCPServer
1 | import socketserver |
2 | |
3 | class TCPHandler(socketserver.BaseRequestHandler): |
4 | ''' |
5 | The request handler class |
6 | ''' |
7 | def handle(self): |
8 | self.data = self.request.recv(1024).strip() |
9 | print("{} connect...".format(self.client_address[0])) |
10 | print(self.data) |
11 | self.request.sendall(self.data.upper()) |
12 | |
13 | if __name__ == "__main__": |
14 | HOST,PORT = "127.0.0.1",9000 |
15 | with socketserver.TCPServer((HOST,PORT),TCPHandler) as server: |
16 | print("TCPServer Starting...") |
17 | server.serve_forever() |
18 | |
19 | ### StreamRequestHandler |
20 | class TCPHandler(socketserver.StreamRequestHandler): |
21 | def handle(self); |
22 | self.data = sefl.rfile.readline().strip() |
23 | print("{} connect...".format(self.client_address[0])) |
24 | print(self.data) |
25 | self.wfile.write(self.data.upper()) |
client:
1 | import socket |
2 | |
3 | HOST,PORT = "127.0.0.1",9000 |
4 | |
5 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: |
6 | sock.connect((HOST,PORT)) |
7 | sock.sendall('hello python'.encode()) |
8 | data = sock.recv(1024) |
9 | print(data.decode()) |
socketserver.UDPServer
1 | import sockerserver |
2 | |
3 | class UDPHandler(sockerserver.BaseRequestHandler): |
4 | def handle(self): |
5 | data = self.request[0].strip() |
6 | socket = self.request[1] |
7 | print("{} connect...").format(self.client_address[0]) |
8 | print(data) |
9 | socker.sendto(data.upper(), self.clietnt_address) |
10 | |
11 | if __name__ == "__main__": |
12 | HOST, PORT = "127.0.0.1",9000 |
13 | with sockerserver.UDPServer((HOST,PORT),UDPHandler): |
14 | server.serve_forever() |
client:
1 | import socket |
2 | |
3 | HOST,PORT = "127.0.0.1",9000 |
4 | |
5 | with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock: |
6 | sock.sendto('hello python'.encode()) |
7 | data = sock.recv(1024) |
8 | print(data.decode()) |