10.python网络编程(socket server 实现并发 part 2)

简介:

一、基于tcp的socket通信的基本原理分析。

基于tcp的socket通信,主要依靠两个循环,分别是连接循环和通信循环。

这个前面的文章有写过,在这里就不再重复了。


二、socketserver实现多并发的原理分析。

1.server类:

1036857-20170505014200961-1776184607.png

2.reques类。

1036857-20170505014309914-771361140.png

类继承关系:

1036857-20170505015158101-334152905.png


1036857-20170505015356492-1711228984.png

示例代码:

import socketserver
import struct
import json
import os
class FtpServer(socketserver.BaseRequestHandler):
    coding='utf-8'
    server_dir='file_upload'
    max_packet_size=1024
    BASE_DIR=os.path.dirname(os.path.abspath(__file__))
    def handle(self):
        print(self.request)
        while True:
            data=self.request.recv(4)
            data_len=struct.unpack('i',data)[0]
            head_json=self.request.recv(data_len).decode(self.coding)
            head_dic=json.loads(head_json)
            # print(head_dic)
            cmd=head_dic['cmd']
            if hasattr(self,cmd):
                func=getattr(self,cmd)
                func(head_dic)
    def put(self,args):
        file_path = os.path.normpath(os.path.join(
            self.BASE_DIR,
            self.server_dir,
            args['filename']
        ))
        filesize = args['filesize']
        recv_size = 0
        print('----->', file_path)
        with open(file_path, 'wb') as f:
            while recv_size < filesize:
                recv_data = self.request.recv(self.max_packet_size)
                f.write(recv_data)
                recv_size += len(recv_data)
                print('recvsize:%s filesize:%s' % (recv_size, filesize))
ftpserver=socketserver.ThreadingTCPServer(('127.0.0.1',8080),FtpServer)
ftpserver.serve_forever()

分析开始:

结合上面的例子,还有类关系图一块看。

ftpserver=socketserver.ThreadingTCPServer(('127.0.0.1',8080),FtpServer)
ftpserver.serve_forever()

查找属性的顺序:ThreadingTCPServer->ThreadingMixIn->TCPServer->BaseServer

  1. 通过ThreadingTCPServer 这个类,实例化出一个ftpserver对象。

    1.2 先从ThreadingTCPServer这个类中找__init__方法,SocketServer的源码中可以看到,它本身并没有__init__方法,这时候就从ThreadingTCPServer所继承的两个父类中去找。从源码中可以看到ThreadingTCPServer一共继承了两个父类,分别是ThreadingMixIn和TCPServer,其中ThreadingMixIn中也没有__init__方法,最终在TCPServer下找到了__init__,此时执行TCPServer下的__init__方法。



       1.3 TCPServer下的__init__方法一共做了四件事,分别是执行了BaseServer类下的__init__方法,创                                    建了socket对象,绑定了IP地址和端口(bind),以及开始listen监听。

        BaseServer类下的__init__方法,做了两件事,为创建出来的对象添加了两个属性,分别                                            是server_address和RequestHandlerClass,其中server_address是服务端绑定的ip地址和端                        口,RequestHandlerClass是前面我们自己创建的FtpServer类。

        (完成了bind和listen操作是因为执行了server_bind和server_active)

        

    2.Serve_forever 实现连接循环。

        2.1前面说了,ftpserver这个对象是由ThreadingTCPServer这个类创建出来的,所以说,默认情况下ftpserver这个对象本身,以及ThreadingTCPServer这个类都没有Serve_forever这个方法,依旧按照上面的套路,阅读源码,从ThreadingTCPServer继承的父类中去找,分别是ThreadingMixIn和TCPServer,在这两个父类中都没有找到,接着去看ThreadingMixIn和TCPServer继承的父类....关于继承顺序的概念在这也不再赘述.....最终在BaseServer中找到了Serve_forever这个方法。


    2.2serve_forever下主要执行self._handle_request_noblock()进而执行request, client_address = self.get_request()(就是TCPServer中的self.socket.accept()),然后执行self.process_request(request, client_address)

在ThreadingMixIn中找到process_request,开启多线程应对并发,进而执行process_request_thread,执行self.finish_request(request, client_address)。


    2.3上述四部分完成了链接循环,本部分开始进入处理通讯部分,在BaseServer中找到finish_request,触发我们自己定义的类的实例化,去找__init__方法,而我们自己定义的类没有该方法,则去它的父类也就是BaseRequestHandler中找....

 


最后总结下创建socketserver的几个步骤。

  1. First, you must create a request handler class by subclassing the BaseRequestHandlerclass and overriding its handle() method; this method will process incoming requests.   


首先你必须创建一个类,这个类必须是BaseRequestHandler的子类,并且这个类必须要有一个handle方法,这个方法用来处理连接进来的请求。


2.Second, you must instantiate one of the server classes, passing it the server’s address and the request handler class.

其次你必须实例化一个服务器类,在实例化的过程中,需要传入服务端地址 以及 那个请求句柄的类。


3.Then call the handle_request() or serve_forever() method of the server object to process one or many requests.

然后,执行服务器对象的handle_request()或 serve_forever()方法 ,来处理一个或多个请求。


4.Finally, call server_close() to close the socket.

最后,执行server_close()这个方法关闭套接字。





      本文转自苏浩智 51CTO博客,原文链接:http://blog.51cto.com/suhaozhi/1923787,如需转载请自行联系原作者






相关文章
|
8月前
|
运维 监控 数据可视化
Python 网络请求架构——统一 SOCKS5 接入与配置管理
通过统一接入端点与标准化认证,集中管理配置、连接策略及监控,实现跨技术栈的一致性网络出口,提升系统稳定性、可维护性与可观测性。
|
11月前
|
机器学习/深度学习 算法 量子技术
GQNN框架:让Python开发者轻松构建量子神经网络
为降低量子神经网络的研发门槛并提升其实用性,本文介绍一个名为GQNN(Generalized Quantum Neural Network)的Python开发框架。
297 4
GQNN框架:让Python开发者轻松构建量子神经网络
|
8月前
|
机器学习/深度学习 大数据 关系型数据库
基于python大数据的青少年网络使用情况分析及预测系统
本研究基于Python大数据技术,构建青少年网络行为分析系统,旨在破解现有防沉迷模式下用户画像模糊、预警滞后等难题。通过整合多平台亿级数据,运用机器学习实现精准行为预测与实时干预,推动数字治理向“数据驱动”转型,为家庭、学校及政府提供科学决策支持,助力青少年健康上网。
|
9月前
|
JavaScript Java 大数据
基于python的网络课程在线学习交流系统
本研究聚焦网络课程在线学习交流系统,从社会、技术、教育三方面探讨其发展背景与意义。系统借助Java、Spring Boot、MySQL、Vue等技术实现,融合云计算、大数据与人工智能,推动教育公平与教学模式创新,具有重要理论价值与实践意义。
|
10月前
|
运维 Linux 开发者
Linux系统中使用Python的ping3库进行网络连通性测试
以上步骤展示了如何利用 Python 的 `ping3` 库来检测网络连通性,并且提供了基本错误处理方法以确保程序能够优雅地处理各种意外情形。通过简洁明快、易读易懂、实操性强等特点使得该方法非常适合开发者或系统管理员快速集成至自动化工具链之内进行日常运维任务之需求满足。
671 18
|
9月前
|
调度 数据库 Python
Python异步编程入门:asyncio让并发变得更简单
Python异步编程入门:asyncio让并发变得更简单
472 5
|
11月前
|
JSON 网络安全 数据格式
Python网络请求库requests使用详述
总结来说,`requests`库非常适用于需要快速、简易、可靠进行HTTP请求的应用场景,它的简洁性让开发者避免繁琐的网络代码而专注于交互逻辑本身。通过上述方式,你可以利用 `requests`处理大部分常见的HTTP请求需求。
797 51
|
10月前
|
数据采集 存储 数据可视化
Python网络爬虫在环境保护中的应用:污染源监测数据抓取与分析
在环保领域,数据是决策基础,但分散在多个平台,获取困难。Python网络爬虫技术灵活高效,可自动化抓取空气质量、水质、污染源等数据,实现多平台整合、实时更新、结构化存储与异常预警。本文详解爬虫实战应用,涵盖技术选型、代码实现、反爬策略与数据分析,助力环保数据高效利用。
531 0
|
11月前
|
存储 监控 算法
基于 Python 跳表算法的局域网网络监控软件动态数据索引优化策略研究
局域网网络监控软件需高效处理终端行为数据,跳表作为一种基于概率平衡的动态数据结构,具备高效的插入、删除与查询性能(平均时间复杂度为O(log n)),适用于高频数据写入和随机查询场景。本文深入解析跳表原理,探讨其在局域网监控中的适配性,并提供基于Python的完整实现方案,优化终端会话管理,提升系统响应性能。
287 4
|
调度 Python
探索Python高级并发与网络编程技术。
可以看出,Python的高级并发和网络编程极具挑战,却也饱含乐趣。探索这些技术,你将会发现:它们好比是Python世界的海洋,有穿越风暴的波涛,也有寂静深海的奇妙。开始旅途,探索无尽可能吧!
327 15

热门文章

最新文章

推荐镜像

更多