socketserver 源码浅读

import SocketServer
class MyServer(SocketServer.BaseRequestHandler):
    def handle(self):       #函数名必须是handle,源码BaseRequestHandler预定义;
        print self.request,self.client_address,self.server  #BaseRequestHandler的__init__定义好的;
        conn = self.request     #每个连接的socket
        conn.sendall('欢迎致电 10086,请输入1xxx,0转人工服务.')
        Flag = True
        while Flag:
            data = conn.recv(1024)
            if data == 'exit':
                Flag = False
            elif data == '0':
                conn.sendall('通话可能会被录音.balabala一大推')
            else:
                conn.sendall('请重新输入.')
if __name__ == '__main__':
    server = SocketServer.ThreadingTCPServer(('127.0.0.1',8009),MyServer)   #实例化ThreadingTCPServer,其实是继承TCPServer类的初始化,需要传入(server_address, RequestHandlerClass),RequestHandlerClass就是MyServer类。
    server.serve_forever()  #启动服务,用select一直在循环执行,继承自BaseServer类的方法serve_forever();

分析这段代码

服务器启动程序后:
1、 执行 TCPServer.__init__ 方法,创建服务端Socket对象并绑定 IP 和 端口
    解释:class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass,ThreadingTCPServer先要执行__init__构造函数,ThreadingMixIn里没有,就去TCPServer类里去找
2、执行 BaseServer.__init__ 方法,将自定义的继承自SocketServer.BaseRequestHandler 的类 MyRequestHandle赋值给self.RequestHandlerClass
    解释:TCPServer构造方法中包含BaseServer.__init__(self, server_address, RequestHandlerClass),所以要把自己定义的类传给BaseServer的构造方法
3、执行 BaseServer.server_forever 方法,While 循环一直监听是否有客户端请求到达 ...
    解释:serve_forever是BaseServer类中的方法,里面有个while循环,一直调用select.select(),r, w, e = _eintr_retry(select.select, [self], [], [],poll_interval)
客户端接入:
4、执行 BaseServer._handle_request_noblock方法
    解释:serve_forever的while循环里有一个判断if self in r:self._handle_request_noblock(),客户端连接句柄发生变化就会把句柄放到r列表里,所以,触发了_handle_request_noblock()。
5、 执行 ThreadingMixIn.process_request 方法,创建一个 “线程” 用来处理请求
    解释:调用process_request方法时,从继承类广度优先原则,所以它先调用ThreadingMixIn类中的process_request
6、执行 ThreadingMixIn.process_request_thread 方法
    解释:t = threading.Thread(target = self.process_request_thread,args = (request, client_address))多线程模块方法,调用self.process_request_thread,此时才真正启动了线程。
7、执行 BaseServer.finish_request 方法,执行 self.RequestHandlerClass()  即:执行 自定义 MyRequestHandler 的构造方法(自动调用基类BaseRequestHandler的构造方法,在该构造方法中又会调用自定义的MyRequestHandler的handle方法)
    解释:连接创建完成,此时开始执行handle方法中的内容,开始和客户端交互,执行完,后面再执行shutdown_request方法关闭连接。
 
import socket
import threading
import select
def process(request, client_address):
    print request,client_address
    conn = request
    conn.sendall('欢迎致电 10086,请输入1xxx,0转人工服务.')
    flag = True
    while flag:
        data = conn.recv(1024)
        if data == 'exit':
            flag = False
        elif data == '0':
            conn.sendall('通过可能会被录音.balabala一大推')
        else:
            conn.sendall('请重新输入.')
sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sk.bind(('127.0.0.1',8002))
sk.listen(5)
while True:
    r, w, e = select.select([sk,],[],[],1)
    print 'looping'
    if sk in r:
        print 'get request'
        request, client_address = sk.accept()
        t = threading.Thread(target=process, args=(request, client_address))
        t.daemon = False
        t.start()
sk.close()

如精简代码可以看出,SocketServer的ThreadingTCPServer之所以可以同时处理请求得益于 select 和 Threading 两个东西,其实本质上就是在服务器端为每一个客户端创建一个线程,当前线程用来处理对应客户端的请求,所以,可以支持同时n个客户端链接(长连接)。
来源: http://www.cnblogs.com/wupeiqi/articles/5040823.html

猜你喜欢

转载自www.cnblogs.com/journey-mk5/p/9616242.html
今日推荐