Jusene's Blog

python 网络服务器框架socketserver

字数统计: 1.4k阅读时长: 5 min
2018/05/12 Share

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())
CATALOG
  1. 1. socketserver
  2. 2. Request Handler对象
  3. 3. Server对象
  4. 4. sockerserver.TCPServer
  5. 5. socketserver.UDPServer