Python3入门之socketserver
socketserver简介
socketserver(python3)/SocketServer(python2)内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理多个客户端请求的socket服务端。每个客户端请求连接到服务器时,socketserver会通过客户端ip/port实例化为一个对象;即创建一个“线程”或者“进 程” 专门负责处理当前客户端的所有请求。

socketserver类
socketserver总共有4个server基类。
- TCPServer:负责处理TCP协议。
- UDPServer:负责处理UDP协议。
- UnixStreamServer:只适用于类unix平台,不常用。
- UnixDatagramServer:只适用于类unix平台,不常用。
- ForkingMixIn/ ThreadingMixIn:实现了核心的进程化或线程化的功能;作为混合类,与服务器类一并使用以提供一些异步特性;这个类不会直接实例化。
- ThreadingTCPServer/UDPServer
- ForkingTCPServer/UDPServer
前4个类会同步处理每一个request,也就是说只有当前的request处理完才会处理下一个request,这种方式显然很不合理,如果当前的request处理过慢的话就会导致“堵塞”。正确的处理方式应该是开辟新的进程或线程去处理不同的request,通过混合继承ForkingMixIn或ThreadingMixIn类即可解决此问题。
socketserver类方法
-
class socketserver.BaseServer:这是模块中的所有服务器对象的超类。它定义了接口,如下所述,但是大多数的方法不实现,在子类中进行细化。
-
BaseServer.fileno():返回服务器监听套接字的整数文件描述符。通常用来传递给select.select(), 以允许一个进程监视多个服务器。
-
BaseServer.handle_request():处理单个请求。处理顺序:get_request(), verify_request(), process_request()。如果用户提供handle()方法抛出异常,将调用服务器的handle_error()方法。如果self.timeout内没有请求收到, 将调用handle_timeout()并返回handle_request()。
-
BaseServer.serve_forever(poll_interval=0.5): 处理请求,直到一个明确的shutdown()请求。每poll_interval秒轮询一次shutdown。忽略self.timeout。如果你需要做周期性的任务,建议放置在其他线程。
-
BaseServer.shutdown():告诉serve_forever()循环停止并等待其停止。python2.6版本。
-
BaseServer.address_family: 地址家族,比如socket.AF_INET和socket.AF_UNIX。
-
BaseServer.RequestHandlerClass:用户提供的请求处理类,这个类为每个请求创建实例。
-
BaseServer.server_address:服务器侦听的地址。格式根据协议家族地址的各不相同,请参阅socket模块的文档。
-
BaseServer.socketSocket:服务器上侦听传入的请求socket对象的服务器。
服务器类支持下面的类变量:
-
BaseServer.allow_reuse_address:服务器是否允许地址的重用。默认为false ,并且可在子类中更改。
-
BaseServer.request_queue_size
请求队列的大小。如果单个请求需要很长的时间来处理,服务器忙时请求被放置到队列中,最多可以放request_queue_size个。一旦队列已满,来自客户端的请求将得到 “Connection denied”错误。默认值通常为5 ,但可以被子类覆盖。
-
BaseServer.socket_type:服务器使用的套接字类型; socket.SOCK_STREAM和socket.SOCK_DGRAM等。
-
BaseServer.timeout:超时时间,以秒为单位,或 None表示没有超时。如果handle_request()在timeout内没有收到请求,将调用handle_timeout()。
下面方法可以被子类重载,它们对服务器对象的外部用户没有影响。
-
BaseServer.finish_request():实际处理RequestHandlerClass发起的请求并调用其handle()方法。 常用。
-
BaseServer.get_request():接受socket请求,并返回二元组包含要用于与客户端通信的新socket对象,以及客户端的地址。
-
BaseServer.handle_error(request, client_address):如果RequestHandlerClass的handle()方法抛出异常时调用。默认操作是打印traceback到标准输出,并继续处理其他请求。
-
BaseServer.handle_timeout():超时处理。默认对于forking服务器是收集退出的子进程状态,threading服务器则什么都不做。
-
BaseServer.process_request(request, client_address) :调用finish_request()创建RequestHandlerClass的实例。如果需要,此功能可以创建新的进程或线程来处理请求,ForkingMixIn和ThreadingMixIn类做到这点。常用。
-
BaseServer.server_activate():通过服务器的构造函数来激活服务器。默认的行为只是监听服务器套接字。可重载。
-
BaseServer.server_bind():通过服务器的构造函数中调用绑定socket到所需的地址。可重载。
-
BaseServer.verify_request(request, client_address):返回一个布尔值,如果该值为True ,则该请求将被处理,反之请求将被拒绝。此功能可以重写来实现对服务器的访问控制。默认的实现始终返回True。client_address可以限定客户端,比如只处理指定ip区间的请求。 常用。
socketserver创建
使用SocketServer创建一个网络服务程序只需要几个简单的步骤:
1. 创建处理request的类,创建方法为:继承BaseRequestHandler类,并重载handle()方法。该方法将被回调用做处理当前接收到的request。
注意:一般的做法是直接继承StreamRequestHandler或者DatagramRequestHandler。比如:
class MyTCPHandler(SocketServer.StreamRequestHandler):
2. 实例化一个server基类(比如TCPServer)的对象,并发服务器地址和处理request的类作为参数传入。
3. 使用server基类对象调用handle_request()或serve_forever()方法,即可处理一个或多个request。
4. 如果需要创建多进程或多线程的服务器程序,则可以通过ThreadingTCPServer/UDPServer或ForkingTCPServer/UDPServer
socketserver代码示例
创建多线程类型的TCP SocketServer
import socketserver class MyTCPHandler(socketserver.BaseRequestHandler): """ 客户端发送a-z字符串,socketserver返回大写 """ def handle(self): #必须要有handle方法;所有处理必须通过handle方法实现 # self.request is the TCP socket connected to the client while True: self.data = self.request.recv(1024).strip() if not self.data: print('The client disconnects actively!') break self.return_client() def return_client(self): #数据处理方法 print("Ip:{0} Port{1}:".format(self.client_address[0], self.client_address[1])) print(self.data.decode('utf8')) # just send back the same data, but upper-cased self.request.sendall(self.data.upper()) if __name__ == "__main__": HOST, PORT = "localhost", 9990 # Create the server, binding to localhost on port 9999 server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler) #实例化一个多线程TCPServer print('Wait client . . .') server.serve_forever()
socket客户端(通过socket创建客户端)
import socket HOST, PORT = "localhost", 9990 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((HOST, PORT)) while True: data = input('Input [a-z]:>>') if data == 'bye': break sock.sendall(bytes(data + "\n", "utf-8")) received = str(sock.recv(1024), "utf-8") print("Sent: {}".format(data)) print("Received: {}".format(received)) sock.close()
***********************************************************
学习永远不晚。——高尔基
***********************************************************

浙公网安备 33010602011771号