博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
socketserver模块解析
阅读量:6867 次
发布时间:2019-06-26

本文共 5258 字,大约阅读时间需要 17 分钟。

  • socketserver模块是基于socket而来的模块,它是在socket的基础上进行了一层封装,并且实现并发等功能。

  •  

    • 看看具体用法:

       
       
       
      ​x
       
       
       
       
      import socketserver                              #1、引入模块
      class MyServer(socketserver.BaseRequestHandler): #2、自己写一个类,类名自己随便定义,然后继承socketserver这个模块里面的BaseRequestHandler这个类
         def handle(self):              #3、写一个handle方法,必须叫这个名字,不写运行父类的pass
             #self.request              #6、self.request 相当于一个conn
             self.request.recv(1024)                  #7、收消息
             msg = '亲,学会了吗'
             self.request.send(bytes(msg,encoding='utf-8')) #8、发消息
             self.request.close()                     #9、关闭连接
          # 拿到了我们对每个客户端的管道,那么我们自己在这个方法里面的就写我们接收消息发送消息的逻辑就可以了
             pass
      if __name__ == '__mian__':
         #thread 线程,现在只需要简单理解线程,别着急,后面很快就会讲到啦,看下面的图
         server = socketserver.ThreadingTCPServer(('127.0.0.1',8090),MyServer)#4、使用socketserver的ThreadingTCPServer这个类,将IP和端口的元祖传进去,还需要将上面咱们自己定义的类传进去,得到一个对象,相当于我们通过它进行了bind、listen
         server.serve_forever()                       #5、使用我们上面这个类的对象来执行serve_forever()方法,他的作用就是说,我的服务一直开启着,就像京东一样,不能关闭网站,对吧,并且serve_forever()帮我们进行了accept
      #注意:
      #有socketserver 那么有socketclient的吗?
      #当然不会有,我要作为客户去访问京东的时候,京东帮我也客户端了吗,客户端是不是在我们自己的电脑啊,并且socketserver对客户端没有太高的要求,只需要自己写一些socket就行了
       
       
    • 简单的应用

       
       
       
      xxxxxxxxxx
       
       
       
       
      #服务端
      import socketserver
      class Myserver(socketserver.BaseRequestHandler):
         def handle(self):
             self.data = self.request.recv(1024).strip()
             print("{} wrote:".format(self.client_address[0]))
             print(self.data)
             self.request.sendall(self.data.upper())
      if __name__ == "__main__":
         HOST, PORT = "127.0.0.1", 9999
         # 设置allow_reuse_address允许服务器重用地址
         socketserver.TCPServer.allow_reuse_address = True
         # 创建一个server, 将服务地址绑定到127.0.0.1:9999
         #server = socketserver.TCPServer((HOST, PORT),Myserver)
         server = socketserver.ThreadingTCPServer((HOST, PORT),Myserver)
         # 让server永远运行下去,除非强制停止程序
         server.serve_forever()
         
      #客服端
      import socket
      HOST, PORT = "127.0.0.1", 9999
      data = "hello"
      # 创建一个socket链接,SOCK_STREAM代表使用TCP协议
      with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
         sock.connect((HOST, PORT))          # 链接到客户端
         sock.sendall(bytes(data + "\n", "utf-8")) # 向服务端发送数据
         received = str(sock.recv(1024), "utf-8")# 从服务端接收数据
      print("Sent:     {}".format(data))
      print("Received: {}".format(received))
       
       

       

  • socketserver模块源码解读

    img

    • 从上图我们可以看出SocketServer主要被抽象为两个主要的类: BaseServer类,用于处理连接相关的网络操作 BaseRequestHandler类,用于实际处理数据相关的操作,SocketServer还提供了两个MixIn类:ThreadingMinxIn和ForkingMixinl 用于扩展server,实现多进程和多线程。

       
       
       
      xxxxxxxxxx
       
       
       
       
      #以下从这几个主要的类开始做整体分析
      #BaseServer类:
        # server_activate
        # serve_forever
        # shutdown
        # service_actions
        # handle_request
        # handlerequest_noblock
        # handle_timeout
        # verify_request
        # process_request
        # server_close
        # finish_request
        # shutdown_request
        # close_request
        # handle_error
      #先看看BaseServer的初始化函数,主要是实现创建server对象,并初始化serve地址和处理请求的类:RequestHandlerClass
      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
         
      #serve_forever函数,创建server对象之后我们会使用server对象开启无限循环,接受一个参数poll_interval,用于表示select轮询的时间,然后进入一个死循环,用select方法进行网络IO的监听,这里通过调用selector.register(self, selectors.EVENT_READ)进行了注册,当ready有返回是,表示有IO连接或者数据,这个时候会调用_handle_request_noblock
      def serve_forever(self, poll_interval=0.5):
         self.__is_shut_down.clear()
         try:
             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()
                     self.service_actions()
         finally:
             self.__shutdown_request = False
             self.__is_shut_down.set()
             
      #handlerequest_noblock函数,即开始处理一个请求,并且是非阻塞。该方法通过get_request方法获取连接,具体的实现在其子类。一旦得到了连接,调用verify_request方法验证请求。验证通过,即调用process_request处理请求。如果中途出现错误,则调用handle_error处理错误,以及shutdown_request结束连接,而verify_request中默认直接返回True,所以当验证通过后讲调用process_request
      def _handle_request_noblock(self):
         try:
             request, client_address = self.get_request()
         except OSError:
             return
         if self.verify_request(request, client_address):
             try:
                 self.process_request(request, client_address)
             except:
                 self.handle_error(request, client_address)
                 self.shutdown_request(request)
         else:
             self.shutdown_request(request)
       # process_request函数, process_request方法是mixin的入口,MixIn子类通过重写该方法,进行多线程或多进程的配置 。调用finish_request完成请求的处理,同时调用shutdown_request结束请求.
      def process_request(self, request, client_address):
         self.finish_request(request, client_address)
         self.shutdown_request(request)
         
      #finish_request函数,关于请求的部分到这里就已经处理完毕,接下来是要对数据的处理,finish_request方法将会处理完毕请求.
      #BaseRequestHandler类,用于实际处理数据相关的操作.
      #初始化函数,该类会处理每一个请求。初始化对象的时候,设置请求request对象。然后调用setup方法,子类会重写该方法,用于处理socket连接。接下来的将是handler和finish方法。所有对请求的处理,都可以重写handler方法。
      def __init__(self, request, client_address, server):
         self.request = request
         self.client_address = client_address
         self.server = server
         self.setup()
         try:
             self.handle()
         finally:
             self.finish()
       
       
       

       

转载于:https://www.cnblogs.com/double-W/p/10704680.html

你可能感兴趣的文章
chmod命令、chown命令、umask命令、chattr命令、lsattr命令
查看>>
APP网站安全漏洞检测服务的详细介绍
查看>>
Knative Eventing 中如何实现 Registry 事件注册机制
查看>>
今天的学习
查看>>
Makefile有三个非常有用的变量。分别是$@,$^,$
查看>>
网络大厂和以色列研究团运用ML打造洪水预测模型
查看>>
Dart | 浅析dart中库的导入与拆分
查看>>
FFMpeg编程1 环境搭建
查看>>
SpringBoot | 第十八章:web应用开发之WebJars使用
查看>>
Web开发:我希望得到的编程学习路线图
查看>>
Hadoop Outline Part 3 (I/O - Avro)
查看>>
Ubuntu16.04下查看软件版本及安装位置
查看>>
hibernate的查询缓存 (转)
查看>>
查看端口占用情况
查看>>
Zend Framework 2 中,定制error 的layout
查看>>
避免linux并发导致的竞态发生
查看>>
Python学习--xml-ElementTree
查看>>
free、ps、netstat、tcpdump命令工具介绍
查看>>
基于oracle数据库的CLOUD备份恢复测试
查看>>
正则取ip地址
查看>>