TreadingTCPServer实现的socket服务器内部会为每个client创建一个线程,该线程用来和客户端进行交互。

1、TreadingTCPServer基础

使用TreadingTCPServer:

  创建一个继承socketserver.BaseRequestHandler的类

  类中必须定义一个名称为handle的方法

  启动TreadingTCPServer

import SocketServer

class MyServer(SocketServer.BaseRequestHandler):

    def handle(self):
        # print self.request,self.client_address,self.server
        conn = self.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('请重新输入.')


if __name__ == '__main__':
    server = SocketServer.ThreadingTCPServer(('127.0.0.1',8009),MyServer)
    server.serve_forever()
View Code


 

import socket


ip_port = ('127.0.0.1',8009)
sk = socket.socket()
sk.connect(ip_port)
sk.settimeout(5)

while True:
    data = sk.recv(1024)
    print 'receive:',data
    inp = raw_input('please input:')
    sk.sendall(inp)
    if inp == 'exit':
        break

sk.close()
View Code

2、TreadingTCPServer源码剖析

TreadingTCPServer的类图关系如下:

内部调用流程为:

  1、启动服务端程序

  2、执行TCPServer.__init__方法,创建服务端socket对象并绑定IP和端口

  3、执行BaseServer.__init__方法,将自定义的继承自socketserver.BaseRequestHandler的类赋值给self.RequestHandlerClass

  4、执行BaseServer.server_forever方法,while循环一直监听是否有客户端请求到达

  5、当客户端链接到达服务器

  6、执行ThreadingMixIn.process_request方法,创建一个线程用来处理请求

  7、执行TreadingMixIn.process_request_thread方法

  8、执行BaseServer.finish_request方法,执行self.RequestHandleClass(),即:执行自定义MyRequestHandle的构造方法(自动调用基类BaseRequestHandler的构造方法,在该构造方法中会调用MyRequestHandler的handle方法)

 

源码精简:

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()
View Code

从精简代码可以看出,socketserver的TreadingTCPServer之所以可以同时处理请求得益于select和Treading两个东西,其实本质上就是在服务器端为每个客户端创建一个线程,当前线程用来处理对应客户端的请求,所以,可以支持同事n个客户端链接(长连接)。

 

posted on 2017-04-20 16:29  自然洒脱  阅读(168)  评论(0编辑  收藏  举报