python TCPServer, StreamRequestHandler设置超时时间timeout
来源:互联网 发布:centos查看文件夹大小 编辑:程序博客网 时间:2024/06/08 12:30
先来大概说一下,网络编程中总是分不开服务器和客户端,所谓的超时也分两种情况,一种是服务器等待客户端连接超时,一种是服务器处理客户端请求超时(可以理解为sever和handle),这两种情况要分别对待。
先来看看等待连接超时的server timeout
python对服务器也有简单的封装,先看看文档。
+------------+ | BaseServer | +------------+ | v +-----------+ +------------------+ | TCPServer |------->| UnixStreamServer | +-----------+ +------------------+ | v +-----------+ +--------------------+ | UDPServer |------->| UnixDatagramServer | +-----------+ +--------------------+这就是基础服务器的继承关系,当然除此之外还有HTTP的服务器HTTPServer继承自TCPServer等。
在基类BaseServer中有一个timeout变量。BaseServer中有一个handle_request函数,源码如下:
def handle_request(self): """Handle one request, possibly blocking. Respects self.timeout. """ # Support people who used socket.settimeout() to escape # handle_request before self.timeout was available. timeout = self.socket.gettimeout() if timeout is None: timeout = self.timeout elif self.timeout is not None: timeout = min(timeout, self.timeout) fd_sets = _eintr_retry(select.select, [self], [], [], timeout) if not fd_sets[0]: self.handle_timeout() return self._handle_request_noblock()可以看到,这里设置了timeout并用了select的复用,select的时间间隔是timeout,如果不设置timeout,那就一直等待。
需要说明的一点,一旦创建了socket服务,那么有两种方法可以开启服务,分别是server_forerver()和handle_request(),handle_request的代码如上,那么server_forerver的代码又是怎样的?如下:
def serve_forever(self, poll_interval=0.5): """Handle one request at a time until shutdown. Polls for shutdown every poll_interval seconds. Ignores self.timeout. If you need to do periodic tasks, do them in another thread. """ self.__is_shut_down.clear() try: while not self.__shutdown_request: # XXX: Consider using another file descriptor or # connecting to the socket to wake this up instead of # polling. Polling reduces our responsiveness to a # shutdown request and wastes cpu at all other times. r, w, e = _eintr_retry(select.select, [self], [], [], poll_interval) if self in r: self._handle_request_noblock() finally: self.__shutdown_request = False self.__is_shut_down.set()注意,这儿的注释有句话:Polls for shutdown every poll_interval seconds. Ignores self.timeout.If you need to do periodic tasks,好吧,这里把ignores和timeout分写两行了,实在是不太注意到。
同样,server_forerver里面同样也用了select多路复用,这里的时间间隔是poll_interval,默认是0.5s,但是对比handle_request函数,server_forerver函数中并没有对handle_timeout,而server_request函数中有两行
if not fd_sets[0]:
self.handle_timeout()
return
在这个地方进行超时处理,这个地方可以对基类的handle_timeout进行覆盖,做我们想做的事,说明的是pyhton中所有的方法默认都是虚函数,所以只要覆盖了就会生效。
来简单梳理一下。当TCPServer创建好之后,有两种开启方式,server_forerver和handle_request,这两种的区别就是server_forever不会处理超时,而handle_request会处理超时。
再来看一下处理超时 handle_timeout
同样的,python对请求的处理也有相关的类,BaseRequestHandler、StreamRequestHandler、DatagramRequestHandler,注意的是BaseRequestHandler中并没有timeout,StreamRequestHandler才有。注释说是 # A timeout to apply to the request socket, if not None.所以这里指的是客户端从发起请求到请求结束超时,假如有恶意的连接攻击,可以设置超时,断开连接。
最后再来整理一下。超时有两种,一种是等待连接超时,一种是处理请求超时,这两种的超时在两个类中
示例代码:
service:
#!/usr/bin/pythonimport socketimport timefrom SocketServer import TCPServer, StreamRequestHandler__author__ = 'meiqizhang'class MyStreamRequestHandlerr(StreamRequestHandler): def __init__(self, request, client_address, server): print('%s create handler...' % (time.time())) StreamRequestHandler.__init__(self, request, client_address, server) def handle(self): self.request.settimeout(3) try: data = self.rfile.readline().strip() time.sleep(5) print('%s recv from client: %s %s' % (time.time(), self.client_address, data)) except socket.timeout as e: print('%s catch an timtout exception. %s(%s)' % (time.time(), e, self.client_address)) self.finish()class SimpleServer(TCPServer): #timeout = 2 def __init__(self, server_address, RequestHandlerClass): #self.timeout = 2 TCPServer.__init__(self, server_address, RequestHandlerClass) def handle_timeout(self): print('%s timeout...' % time.time())def main(): server = SimpleServer(('127.0.0.1', 888), MyStreamRequestHandlerr) server.timeout = 2 print('server running...') #server.serve_forever() while True: server.handle_request()if '__main__' == __name__: main()
对于连接超时的设置三种方法都可以,可以直接写timeout = 2,也可以self.timeout = 2,还可以server.timeout = 2,而对于处理请求的超时的设置,要在handle中通过self.request.settimeout(3)来设置。
client:
#!/usr/local/bin/python#coding=utf-8import timeimport socketsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)sock.connect(('localhost', 888))print("connect server success!")data = 'hello world'sock.send(data)time.sleep(10)data = sock.recv(1023)print(data)sock.close()先运行server,因为没有连接,每隔2秒会打印出timeout。接着运行client,在收到请求后handler中暂停了5秒,超过了处理请求超时时间3秒,打印出catch an timtout exception. timed out。
最后说一点:行TCPServer收到客户端的accept连接请求,就会创建一个handler对象对其进行请求处理(会把accept返回是socket传递到handler)
- python TCPServer, StreamRequestHandler设置超时时间timeout
- weblogic设置session-timeout超时时间
- HttpClient超时时间 timeout
- 设置超时,timeout,socket
- 20.2.3.Setting the Login Timeout设置登录超时时间
- Python urllib2 设置超时时间
- Python urllib2 设置超时时间
- curl默认超时(timeout)时间
- Transactional超时时间timeout控制
- dubbo配置timeout超时时间
- HttpClient 4.5.2版本设置连接超时时间-CloseableHttpClient设置Timeout
- HttpClient 4.5.2版本设置连接超时时间-CloseableHttpClient设置Timeout
- HttpClient 4.5.2版本设置连接超时时间-CloseableHttpClient设置Timeout
- python http,或者soap设置超时时间
- StreamRequestHandler
- Python爬虫--timeout设置--防止访问时间过长造成假死
- haproxy timeout server 46000 后台超时时间
- [VB.NET]设置remoting超时timeout代码
- Oracle 11g安装图文教程
- Android——线程通信 HandlerThread
- eclipse中报 无法加载主类 问题 但在java命令能编译过
- JavaCC options
- Prime Ring Problem
- python TCPServer, StreamRequestHandler设置超时时间timeout
- 机器学习中的范数规则化之(二)核范数与规则项参数选择
- struts中透过反射给领域对象赋值的方法
- 关于静态和非静态
- 11.13
- JavaCC LOOKAHEAD option
- C语言 新手学习
- VS2013转换VC6.0项目失败解决办法
- JavaCC jjtTree options