python成长之路10——socketserver源码分析

 1 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0)
 2 
 3 参数一:地址簇
 4     socket.AF_INET    ipv4(默认)
 5     socket.AF_INET6  ipv6
 6 
 7     socket.AF_UNIX   本地进程间通信
 8 
 9 参数二:类型
10     socket.SOCK_STREAM    流式socket,TCP(默认)
11     socket.SOCK_DGRAM     数据报式socket,UDP
12     socket.SOCK_RAW         原始套接字,ICMP,IGMP
13     socket.SOCK_RDM         可靠的UDP形式
14     socket.SOCK_SEQPACKET    可靠的连续数据包服务
15 
16 参数三:协议
17     0 (默认) 与特定地址家族相关的协议,如果是0,则系统会根据地址格式和套接类别,自动选择一个合适的协议
18 
19 s.bind(ip_port) 
20 s.listen(backlog)  backlog:最大挂起数
21 s.setblocking(bool)  是否阻塞(默认为True),如果设为False,那么accept和recv时一旦无数据就会报错
22 s.accept() 默认阻塞的
23 s.connect(ip_port)连接出错会报错
24 s.connect_ex(ip_port)  连接成功返回0,出错返回编码
25 s.close()
26 s.recv(1024)   1024为最多接收的字节
27 s.recvfrom(1024)  返回值是元祖(data,address,)主要用于UDP
28 s.send()   发送的是字节(3.5)   不一定把所有消息都发完
29 s.sendall()    都发完
30 s.sendto(数据,address)  指定远程地址,主要用于UDP协议
31 s.settimeout(timeout)  timeout 浮点数 单位秒,None为没有超时期 
32 s.getpeername()    返回连接套接字的远程地址 元祖(ip_port)用于TCP
33 s.getsockname()    返回套接字字节的自己的地址 也是元祖 (ip_port) 用于TCP
34 s.fileno()    套接字的文件描述符        
35 
36 socket功能
socket功能

上面又复习了一次socket

下面我们开始分析socketserver的源码:

首先先贴出socketserver各类间的继承关系:

 

 

以上两个图包含了socketserver里的所有类和函数,方便以后查找他们之间的继承关系!图中“1”代表先继承,“2”代表后继承

现在我们来分析下面这段代码:

#/usr/bin/env python
#-*- coding:utf-8 -*-
#Authot:Zhang Yan

import socketserver
ip_port=("127.0.0.1",9999,)
class MyServer(socketserver.BaseRequestHandler):
    def handle(self):
        pass
obj=socketserver.ThreadingTCPServer(ip_port,MyServer)
obj.serve_forever()

MyServer类的继承关系如下:

obj=socketserver.ThreadingTCPServer(ip_port,MyServer)
构建obj对象,执行ThreadingTCPServer类的__init__方法,所以obj是ThreadingTCPServer的对象
从下图可以看出执行的是TCPServer里的init方法

查看此段源码:
def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
    """Constructor.  May be extended, do not override."""
    BaseServer.__init__(self, server_address, RequestHandlerClass)  #在TCPServer的init方法里执行BaseServer的init方法
    self.socket = socket.socket(self.address_family,
                                self.socket_type)   #构建socket对象
    if bind_and_activate:
        try:
            self.server_bind()    #socket的bind方法
            self.server_activate() #socket的listen方法
        except:
            self.server_close()    #socket的close方法
            raise
TCPserver的init
def __init__(self, server_address, RequestHandlerClass):
    """Constructor.  May be extended, do not override."""
    self.server_address = server_address
    self.RequestHandlerClass = RequestHandlerClass
    self.__is_shut_down = threading.Event()  #执行threading.Event的init方法,构建对象
    self.__shutdown_request = False
BaseServer的init
obj.serve_forever(),因为obj是ThreadingTCPServer的对象,所以先在ThreadTCPServer里找,没有的话在他的父类里找,如下图:

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:
        # 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.
        with _ServerSelector() as selector:
            selector.register(self, selectors.EVENT_READ)

            while not self.__shutdown_request:
                ready = selector.select(poll_interval)
                if ready:
                    self._handle_request_noblock()  #其他地方先不考虑,先看这两行,_handle_request_noblock是BaseServer的私有方法
                self.service_actions()   #self是obj,是ThreadTCPServer的对象,需要根据继承关系找到service_actions()方法
    finally:
        self.__shutdown_request = False
        self.__is_shut_down.set()
BaseServer的serve_forever

 

 


 

 

posted @ 2016-07-11 14:37  meitangyanyan  阅读(197)  评论(0编辑  收藏  举报