socketserverhtml
此模块简化了socket的编写。python
一、它有一个基类,定义了如何创建链接。BaseServer提供了服务类接口,BaseServer使用了select建立了多线程。BaseServer下面有四个类:TCPServer、UnixStreamServer、UDPserver、UnixDatagramServer。json
二、它还提供了请求处理类:定义了如何处理用户数据。定义了三个方法setup\handler\finish,的接口,使用时,从新写对应方法。服务器
三、使用Forktheard和多线程
BaseServer模块结构:socket
服务处理类方法: |
做用 |
BaseServer |
超类,提供了API,并利用select建立了多线程。不能直接调用它使用。 |
TCPServer |
建立每一个进程的socket,传输TCP数据。同时,也是一个基类。 |
UDPServer |
传输UDP数据。 |
UnixStreamServer |
Unix下使用 |
UnixDatagramServer | Unix下使用 |
ThreadingTCPServer | socketserver多路复用版。UDPServer\UnixStreamServer\UnixDatagramServer的多路复用版前加Threading |
服务处理类BaseServer的方法 |
做用 |
fileno() |
返回服务器监听套接字的整数文件描述符。一般用来传递给select.select(), 以容许一个进程监视多个服务器。 |
handle_request() |
处理单个请求。处理顺序:get_request(), verify_request(), process_request()。函数 若是用户提供handle()方法抛出异常,将调用服务器的handle_error()方法。测试 若是self.timeout内没有请求收到, 将调用handle_timeout()并返回handle_request()。 |
serve_forever(poll_interval=0.5) | 处理请求,直到一个明确的shutdown()请求。每poll_interval秒轮询一次shutdown。忽略self.timeout。若是你须要作周期性的任务,建议放置在其余线程。 |
shutdown() |
告诉serve_forever()中止。for python2.6。 |
address_family |
地址簇。socket.AF_INET等 |
HandlerRequestClass |
用户提供的请求处理类,为每个请求建立一个实例。 |
server_address |
侦听的服务器地址。 |
socketSocket |
服务器上侦听传入的请求socket对象的服务器。 |
下面方法能够被子类重载,它们对服务器对象的外部用户没有影响。 | |
finish_request() | 实际处理RequestHandlerClass发起的请求并调用其handle()方法。 经常使用。 |
get_request() | 接受socket请求,并返回二元组包含要用于与客户端通讯的新socket对象,以及客户端的地址。 |
handle_error(request, client_address) | 若是RequestHandlerClass的handle()方法抛出异常时调用。默认操做是打印traceback到标准输出,并继续处理其余请求。 |
handle_timeout() | 超时处理。默认对于forking服务器是收集退出的子进程状态,threading服务器则什么都不作 |
process_request(request, client_address) |
调用finish_request()建立RequestHandlerClass的实例。若是须要,此功能能够建立新的进程或线程来处理请求,ForkingMixIn和ThreadingMixIn类作到这点。经常使用。 |
server_activate() | 经过服务器的构造函数来激活服务器。默认的行为只是监听服务器套接字。可重载。 |
server_bind() | 经过服务器的构造函数中调用绑定socket到所需的地址。可重载。 |
verify_request(request, client_address) | 返回一个布尔值,若是该值为True ,则该请求将被处理,反之请求将被拒绝。此功能能够重写来实现对服务器的访问控制。默认的实现始终返回True。client_address能够限定客户端,好比只处理指定ip区间的请求。 经常使用。 |
服务处理类的变量(属性): |
做用 |
allow_reuse_address |
是否容许地址重用,默认是False,能够在子类里更改。 |
request_queue_size |
请求队列的大小。若是单个请求须要很长的时间来处理,服务器忙时请求被放置到队列中,最多能够放request_queue_size个。一旦队列已满,来自客户端的请求将获得 “Connection denied”错误。默认值一般为5 ,但能够被子类覆盖。 |
socket_type |
服务器使用的套接字类型,socket.SOCK_STREAM和socket.SOCK_DGRAM等。 |
timeout |
超时时间。以秒为单位,或 None表示没有超时。若是handle_request()在timeout内没有收到请求,将调用handle_timeout()。 |
请求处理类的方法: |
做用 |
setup() |
处理请求以前的方法,能够初始化。 |
handle() |
处理请求的方法,处理与Client交互内容。 |
finish() |
handler()处理完成后运行的方法。用于释放和清理。 |
#服务端: import socketserver class Mysite(socketserver.BaseRequestHandler): # 必须继承socketserver基类 def handle(self): # 重写基类里的handler()方法,在这个方法里处理接收、发送请求 while True: recv_data = self.request.recv(1024) data = json.loads(recv_data.decode()) # 为何用json?,由于我喜欢。。这包装数字、字符、列表等等数据类型通吃 print(data) if data.lower() == "exit": # 检测到exit退出 print("客户端退出!") break self.request.send(json.dumps(data.lower()).encode()) # 发送转换小写的数据给客户端,而后进入到下一个循环 my_server = socketserver.TCPserver(("localhost", 9999), Mysite) # 实例化socketserver,并传送服务器ip、port和子类 my_server.serve_forever() # 客户端 import socket class Myclient(object): def __init__(obj): # 接收一个socket实例化的对象 self.conn = obj def handle(self,ip,prot): # 定义一个数据交互的方法 self.conn.connect((ip,port)) # 绑定连接,其它把它放在init方法里是否是会更好? while Ture: # 循环发送、接收数据 cmd = input('输入转换的字符,exit退出!') if cmd.strip().lower() == 'exit': # 若是输入EXIT退出 print('退出!') break self.conn.send(json.dumps(cmd).encode()) # 发送输入的数据 recv_data = self.conn.recv(1024) # 接收服务器转换后的数据 data = json.loads(recv_data.decode()) # json解码 print('转换的:{}'.format(data)) my_socket = socket.socket() # 实例化socket对象 my_client = Myclient(my_socket) # 实例化自定义类,并传入实例化的socket对象 my_client.handle("localhost",9999) # 调用数据交互方法 """以上代码博客里手打,未经测试。 """
其它参考资料:
https://www.cnblogs.com/MnCu8261/p/5546823.html