热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:socketserver模块解析

本文由编程笔记#小编为大家整理,主要介绍了socketserver模块解析相关的知识,希望对你有一定的参考价值。
本文由编程笔记#小编为大家整理,主要介绍了socketserver模块解析相关的知识,希望对你有一定的参考价值。





  • 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 + "
      "
      , "utf-8")) # 向服务端发送数据

         received = str(sock.recv(1024), "utf-8")# 从服务端接收数据

      ?

      print("Sent:     {}".format(data))

      print("Received: {}".format(received))






       

       


       






  • socketserver模块源码解读

    技术图片



    • 从上图我们可以看出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()







       

       


       







html>
推荐阅读
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • javascript  – 概述在Firefox上无法正常工作
    我试图提出一些自定义大纲,以达到一些Web可访问性建议.但我不能用Firefox制作.这就是它在Chrome上的外观:而那个图标实际上是一个锚点.在Firefox上,它只概述了整个 ... [详细]
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • WebSocket与Socket.io的理解
    WebSocketprotocol是HTML5一种新的协议。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送 ... [详细]
  • 使用正则表达式爬取36Kr网站首页新闻的操作步骤和代码示例
    本文介绍了使用正则表达式来爬取36Kr网站首页所有新闻的操作步骤和代码示例。通过访问网站、查找关键词、编写代码等步骤,可以获取到网站首页的新闻数据。代码示例使用Python编写,并使用正则表达式来提取所需的数据。详细的操作步骤和代码示例可以参考本文内容。 ... [详细]
  • 本文介绍了django中视图函数的使用方法,包括如何接收Web请求并返回Web响应,以及如何处理GET请求和POST请求。同时还介绍了urls.py和views.py文件的配置方式。 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • 延迟注入工具(python)的SQL脚本
    本文介绍了一个延迟注入工具(python)的SQL脚本,包括使用urllib2、time、socket、threading、requests等模块实现延迟注入的方法。该工具可以通过构造特定的URL来进行注入测试,并通过延迟时间来判断注入是否成功。 ... [详细]
  • 移动端常用单位——rem的使用方法和注意事项
    本文介绍了移动端常用的单位rem的使用方法和注意事项,包括px、%、em、vw、vh等其他常用单位的比较。同时还介绍了如何通过JS获取视口宽度并动态调整rem的值,以适应不同设备的屏幕大小。此外,还提到了rem目前在移动端的主流地位。 ... [详细]
  • 树莓派语音控制的配置方法和步骤
    本文介绍了在树莓派上实现语音控制的配置方法和步骤。首先感谢博主Eoman的帮助,文章参考了他的内容。树莓派的配置需要通过sudo raspi-config进行,然后使用Eoman的控制方法,即安装wiringPi库并编写控制引脚的脚本。具体的安装步骤和脚本编写方法在文章中详细介绍。 ... [详细]
author-avatar
我叫巴吉度
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有