SocketServer模块分析

来源:互联网 发布:win7网吧优化工具 编辑:程序博客网 时间:2024/04/29 19:35

本文利用SocketServer模块完成一个简单的服务端程序,能将接收到的内容回写给客户端。然后详细分析该例子的框架。

先看例子

# -*- coding: utf-8 -*-from time import ctimefrom SocketServer import TCPServer, StreamRequestHandlerhost = ''port = 50000addr = (host, port)class MyRequestHandler(StreamRequestHandler):    def handle(self):        print('...connected from:', self.client_address)        self.wfile.write('[%s] %s' % (ctime(), self.rfile.readline()))        line = self.rfile.readline()        while line != '\r\n':            self.wfile.write('[%s] %s' % (ctime(), line))            line = self.rfile.readline()tcpServ = TCPServer(addr, MyRequestHandler)print('waiting for connection...')tcpServ.serve_forever()

用浏览器访问“127.0.0.1:50000”,将呈现如下结果:
Alt text
这些信息是HTTP协议中请求信息,第一行表示请求方式为GET,URL相对地址是/,协议版本HTTP/1.1,以下为请求信息头。

一、服务端逻辑结构

Alt text

  1. TCPServer接收客户端socket;
  2. TCPServer验证客户端socket,实质为空操作,它留给子类对之实现;
  3. TCPServer将客户端socket递交给MyRequestHandler;
  4. MyRequestHandler将接收到的内容发送给客户端,(实际上有个空行\r\n没有发送)。

二、服务端代码框架

Alt text

代码流程看上面的图应该很清楚,但有几点实现细节再详述一下:

  • socket属性设置,其中可以设置两个属性:socket.SO_REUSEADDRsocket.TCP_NODELAY分别为设置socket端口复用(防止socket关闭后依然占用端口)不使用Nagle算法(TCP/IP中允许小包发送);
  • 安全关闭服务端,在其它线程调用BaseServer.shutdown(),该机制利用信号量threading.Event()和布尔变量__shutdown_request实现服务端在关闭时能保证BaseServer.serve_forever能运行完当前循环。
  • 捕获select()异常,关于errno.EINTR的解释:系统read()返回0,表示读取正常,如果在读的过程中遇到中断,则返回-1,并将errno置为EINTR;系统write()返回0表示无法写,如果遇到中断,则返回-1,也将errno置为EINTR;所以_eintr_retry()在设计时遇到中断则会重次监控;
  • 关闭socket,socket关闭有两步:request.shutdown(socket.SHUT_WR)request.close(),第一次是关闭socket读写,第二次是使socket引用计数-1。
0 0
原创粉丝点击