Python Basic - socketserver

简介

socketserver 用于实现服务器可以多并发接收请求时。socketserver的相关功能已经被打包成一个模块。使用时需要导入这个模块即可使用其中的方法。

import socketserver

class MyServer(socketserver.BaseRequestHandler): #是一个基础服务类,用于监控,绑定IP地址等操作

    def handle(self):#客户端请求处理的方法,所有的请求交互都在handle里执行
        print("服务端启动......")
        while True:
            conn = self.request # 在源码中可以查看到,request就是创建对象时传入进去的服务端的IP地址与端口。每一个请求都会实例化MyTCPHandler(socketserver.BaseRequestHandler):
            print(self.client_address)
            while True:
                client_data = conn.recv(1024)
                print(str(client_data,"utf8"))
                print("waiting......")
                server_response = input(">>>:")
                conn.sendall(bytes(server_response,"utf8"))
                #conn.sendall(client_data)
            conn.close()


if __name__ == "__main__":
    server = socketserver.ThreadingTCPServer(("127.0.0.1",9200),MyServer)
    server.serve_forever()

import socket

ip_port = ("127.0.0.1",9200)
sk = socket.socket()
sk.connect(ip_port)
print("客户端已启动:")

while True:
    inp = input(">>>:")
    sk.sendall(bytes(inp,"utf8"))
    if inp == "exit":
        break
    server_response = sk.recv(1024)
    print(str(server_response,"utf8"))

sk.close()

socketserver 简介

python 将网络服务抽象成两个订的类,一个是Sever类,用于处理连接相关的网络操作,另外一个则是RequestHandler类,用于处理数据相关的操作。并且提供两个MixIn类,用于扩展Server,实现多进程或多线程。

Server类

在Python的socketserver中,共包含5种Server类:

  1. BaseServer:不直接对外服务
  2. TCPServer:提供TCP连接的服务
  3. UDPServer:提供UDP连接的服务
  4. UnixStreamServer:不常用,主要应用在AF_unix中使用
  5. UnixDatagramServer:不常用,主要应用在AF_unix中使用

################################################################
There are five classes in an inheritance diagram, four of which represent
synchronous servers of four types:

    +----------------+
    | BaseServer |
    +----------------+
        |
        v
    +---------------+********* +-------------------------+
    | TCPServer |------->| UnixStreamServer |
    +---------------+*********+-------------------------+
          |
          v
    +---------------+*********+-----------------------------+
    | UDPServer |------->| UnixDatagramServer |
    +---------------+*********+-----------------------------+

###############################################################

class BaseServer:

"""Base class for server classes.

class TCPServer(BaseServer):

"""Base class for various socket-based server classes.

Defaults to synchronous IP stream (i.e., TCP)

class UDPServer(TCPServer):

"""UDP server class."""

RequestHandler类

所有的RequestHandler类都继承BaseRequestHandler类。

创建一个socketserver

至少包含以下步骤:

  1. 必需创建一个“request handler”的类 做为BaseRequestHandler的子类,并且重写它的"handler()"方法,这个方法用于处理客户端请求。
  2. 必需通过这个子类创建一个相应的对象,传递服务器的IP地址和这个“request handler”类。
  3. 使用handle_request() 或者 serve_forever()方法,这个个server的对象这处理一个或者多个请求
  4. 最后,使用server_close()关闭这个socket。

分析代码的执行过程

  1. 运行“server = socketserver.ThreadingTCPServer((“127.0.0.1”,9200),MyServer)”,所以找先到到ThreadingTCPServer()
  2. 步骤1中其实是一个通过类创建对象的过程,所以在创建对象的时候会自动执行相应类中的“__init__()”方法.
  3. 通过查看源码,找到了“class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass”类,但是没有定义任何方法,所以往父类查找。
  4. 根据父类查找顺序,先找左边的父类“ThreadingMixIn”。发现其下面并没有“__init__()”方法.,所以找“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)
        self.socket = socket.socket(self.address_family,
                                    self.socket_type)
        if bind_and_activate:
            try:
                self.server_bind()
                self.server_activate()
            except:
                self.server_close()
                raise

3个参数需要传递:1,服务器的IP地址与端口,2,RequestHandlerClass.3,默认设置为True,所以基本不用管,这也是为什么在写代码的时候。socketserver.ThreadingTCPServer((“127.0.0.1”,9200),MyServer)

  1. 在步骤4中的代码,将“BaseServer.init(self, server_address, RequestHandlerClass)”将传入的参数交给了父类的“__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()
        self.__shutdown_request = False
* 将传入的服务器的IP地址交给定义的对象,是一个赋值的过程
* 会话的RequestHandlerClass类定义为对象的处理请求的类,是一个赋值的过程
* 后两个先不用考虑
  1. 再执行第4步骤中的“self.socket = socket.socket(self.address_family, self.socket_type)” 创建了一个套接字,第一个参数为address_family,为对象的地址族,第二个参数为套接字的类型,这两个参数在源码中有默认的定义:
    address_family = socket.AF_INET

    socket_type = socket.SOCK_STREAM

到此,套接字创建完成。

  1. 再执行步骤4中的剩下的代码:
        if bind_and_activate:
            try:
                self.server_bind()
                self.server_activate()
            except:
                self.server_close()
                raise

如果“bind_and_activate‘为True的情况下(默认为True),self.server_bind() 绑定,self.server_activate()激活

    def server_bind(self):
        """Called by constructor to bind the socket.

        May be overridden.

        """
        if self.allow_reuse_address:
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.socket.bind(self.server_address)
        self.server_address = self.socket.getsockname()

    def server_activate(self):
        """Called by constructor to activate the server.

        May be overridden.

        """
        self.socket.listen(self.request_queue_size)

如果有错误的话,则关闭server,并报一个错。

  1. 至此,已经创建了套接字,并绑定在了提供的服务器的IP地址与端口上。
  2. 从这里开始执行的是“server.serve_forever()”
  3. server是通过类创建的一对象,现在执行的是对象里面的serve_forever() 方法
  4. 查看源码:
    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)
                    # bpo-35017: shutdown() called during select(), exit immediately.
                    if self.__shutdown_request:
                        break
                    if ready:
                        self._handle_request_noblock()

                    self.service_actions()
        finally:
            self.__shutdown_request = False
            self.__is_shut_down.set()
  • self.__is_shut_down.clear()
  • 将程序运行起来
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值