SocketServer源码学习(二)

SocketServer 中非常重要的两个基类就是:BaseServer 和 BaseRequestHandler
在SocketServer 中也提供了对TCP以及UDP的高级封装,这次我们主要通过分析关于TCP的处理逻辑来对SocketServer模块进行一个很好的理解和学习

TCPServer

TCPServer 继承了BaseServer,初始化的时候,进行了socket套接字的创建。

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

在这里我们看到了我们非常熟悉的关于socket的创建的内容:
self.socket = socket.socket(self.address_family, self.socket_type)
通过socket模块创建了socket对象,接着调用了server_bind和server_activate

server_bind

源码内容如下:

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()

这里我们看到了非常熟悉的操作socket.bind方法,以及设置了socket的相关属性

server_activate

源码内容如下:

def server_activate(self):"""Called by constructor to activate the server.May be overridden."""self.socket.listen(self.request_queue_size)

同样的这里的调用也非常简单就是执行了socket.listen

get_request

在TCPServer类中我们还看到了get_request方法,源码内容如下:

def get_request(self):"""Get the request and client address from the socket.May be overridden."""return self.socket.accept()

这个的调用其实我们可以在BaseServer这个基类中看到,我们之前看过关于BaseServer中这个基类的源码
我们可以从我们调用BaseServer基类中的serve_forever方法查看,这里是调用了_handle_request_noblock方法,我继续查看_handle_request_noblock这个源码

def _handle_request_noblock(self):"""Handle one request, without blocking.I assume that selector.select() has returned that the socket isreadable before this function was called, so there should be no risk ofblocking in get_request()."""try:request, client_address = self.get_request()except OSError:returnif 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来处理请求,继续查看源码:

def process_request(self, request, client_address):"""Call finish_request.Overridden by ForkingMixIn and ThreadingMixIn."""self.finish_request(request, client_address)self.shutdown_request(request)def finish_request(self, request, client_address):"""Finish one request by instantiating RequestHandlerClass."""self.RequestHandlerClass(request, client_address, self)

从上面的代码我们可以到最后是在finish_request中实例化了RequestHandlerClass
我们 这个时候查看一下BaseRequestHandler这个基类的源码如下:

class BaseRequestHandler:"""Base class for request handler classes.This class is instantiated for each request to be handled.  Theconstructor sets the instance variables request, client_addressand server, and then calls the handle() method.  To implement aspecific service, all you need to do is to derive a class whichdefines a handle() method.The handle() method can find the request as self.request, theclient address as self.client_address, and the server (in case itneeds access to per-server information) as self.server.  Since aseparate instance is created for each request, the handle() methodcan define other arbitrary instance variables."""def __init__(self, request, client_address, server):self.request = requestself.client_address = client_addressself.server = serverself.setup()try:self.handle()finally:self.finish()def setup(self):passdef handle(self):passdef finish(self):pass

在初始化函数里我们看到了调用setup()方法,这setup在StreamRequestHandler会被重写

StreamRequestHandler

TCPServer实现了使用tcp套接字的网络服务,Handler方面则是对应的StreamRequestHandler。它继承了BaseRequestHandler。基类的setup方法和finish方法被它重写,用于通过连接实现缓存文件的读写操作。

setup方法

源码内容如下:

def setup(self):self.connection = self.requestif self.timeout is not None:self.connection.settimeout(self.timeout)if self.disable_nagle_algorithm:self.connection.setsockopt(socket.IPPROTO_TCP,socket.TCP_NODELAY, True)self.rfile = self.connection.makefile('rb', self.rbufsize)self.wfile = self.connection.makefile('wb', self.wbufsize)

这里主要设置了对应连接的属性,其中创建了两个对象非常重要:
一个可读(rfile)和一个可写(wfile)的“文件”对象
但是实际并不是创建了文件,而是封装了读取数据和发送数据的操作,抽象成了对文件的操作
可以理解:
self.rfile 就是读取客户端数据的对象,它有一些方法可以读取数据。self.wfile则是用来发送数据给客户端的对象。

整理流程(TCP)

实现TCP服务需要使用TCPServer和StreamRequestHandler共同协作

 

转载于:https://www.cnblogs.com/zhaof/p/8890600.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/267231.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Yum命令解析

Yum配置文件位于/etc/yum.conf和/etc/yum.repos.d/CentOS-Base.repo目录下 使用yum时注意:必须使用root身份来执行yum;yum配置文件内的镜像站点必须能与自己进行网络连接;镜像站点越近,带宽越大越好,方便下载。 [rootl…

430f149有几种封装类型_高速光调制器的发展与封装技术研究

共读好书汪冰 黄平 杨磊摘 要:文章分析了100 Gbps(以下简称100 G)以太网光通信光调制器及其封装的技术发展动向,对比分析了10 G/40 G/100 G高速光调制器及其封装的结构特点。通过对高速光调制原理的浅析,论述了40 G/100 G高速光调制器在100 …

异常:没有找到本地方法库,java.lang.UnsatisfiedLinkError: no trsbean in java.library.path

1.问题描述 迁移环境中遇到这个问题 : Fri Apr 20 15:22:31 CST 2018, Exception:500004___-500004,没有找到本地方法库,java.lang.UnsatisfiedLinkError: no trsbean in java.library.path 1 Fri Apr 20 15:22:31 CST 2018, TRSException:500004___-500004,没有找到本地方法库…

js将docx转换为html,js 将word转换Html

WalkingPoisons Word-to-HTML sample Click the "save" button to save the file "C:/test.doc" to "C:/test.htm":

vsftp账号_Linux入门-CentOS7安装vsftp

前言vsftpd是用于类Unix系统(包括Linux)的FTP服务器。那怎么搭建呢?请看下文在CentOS7 64位进行安装。为了调试顺利,关闭selinux,防火墙iptables一.yum安装vsftp# yum -y install vsftpd二.启动服务# systemctl start vsftpd.service三.配置文…

android n模拟器,BlueStacks推出Android N模拟器

原标题:BlueStacks推出Android N模拟器IT之家1月23日消息,相信有不少玩家都有过在电脑上玩手游的经历,打怪升级这类游戏在操作似乎还是交给键盘和鼠标比较高效,电脑端体验安卓游戏自然就要用到模拟器了,但是尴尬的是似…

为UIKeyboardTypeNumberPad增加自定义按键

在 iPhone 上面開發應用程式時, 在使用輸入鍵盤時, 或多或少都會遇到客制化鍵盤的問題, 這邊筆者以簡單的數字鍵盤來示範客制化的動作. 這部份我想網路上已經有不少 sample code , 但大部份基本上都是以 SDK 3.x 的版本去實作, 以"特定寫法"來實作客制化在 iOS4 會有…

Unity 内建数据索引

看到多少补多少 顶点输入类型 UnityCG.cginc Line:58 struct appdata_base {float4 vertex : POSITION;float3 normal : NORMAL;float4 texcoord : TEXCOORD0;UNITY_VERTEX_INPUT_INSTANCE_ID };struct appdata_tan {float4 vertex : POSITION;float4 tangent : TANGENT;float…

车载安卓中控改鸿蒙,教你改装车子中控安卓大屏,看一遍你就会了,改完后低配秒变高配...

因为我这个车子年代比较久了,所以没有中控大屏,需要导航的时候我都是把手机放在出风口支架这个地方,这种磁吸的支架有时候过减速杠一震动就掉下来了,我又不想在上面粘什么东西,所以干脆就花几百块钱买了一个能够插手机…

pip 删除安装包_Python中PIP的快速指南

无论您是Python新手还是有经验的Python开发人员,不使用pip安装命令是不可能编写或开发Python应用程序的。在这篇文章中,我将对Pip进行详细介绍。Pip是Python Package Manager的缩写。当您在系统上安装python时,它附带了一组预定义的包&#x…

海量数据前N大

最大堆即大根堆 -- 求前n小最小堆即小根堆 -- 求前n大比如求前n小,对于当前元素,和最大堆的堆顶元素(即堆最大值)比较,如果小于堆顶元素,则替换堆顶元素,并调整堆。这样扫描一遍就可以得到最小的…

react项目在ie空白解决

先安装babel-polyfill npm install babel-polyfill --save 2.在入口文件(main.js)最上方将其import进来 import babel-polyfill // 下面是别的代码,不需要动 import Vue from vue import App from ./App转载于:https://www.cnblogs.com/lcosima/p/8893799.html

元素不包括_干货 | FDA法规对元素杂质的限度控制及计算方法

元素杂质又称重金属,重金属原义指比重大于5的金属,元素杂质包括可能存在于原料、辅料或制剂中,来源于合成中催化剂残留、药品生产制备过程中引入或辅料中存在的、生产设备引入、或容器密闭系统引入。某些元素杂质不仅对药品的稳定性、保质期产…

web 日志分析工具 awstats 简单安装

awstats安装使用awstats是一个开源的日志分析工具,用perl编写。感觉还不错,把安装记录写下,也许有人用的到。可以分析大部分标准日志数据,如apache的,nginx的都可以首先下载awstats工具,http://awstats.sou…

MyOffic(经理评分)

1 public class SE2 {3 //员工类4 private int id;5 6 public int Id7 {8 get { return id; }9 set { id value; } 10 } 11 private string name; 12 13 public string Name 14 …

android二分查找法简书,【PYTHON】二分查找算法

二分查找:在一段数字内,找到中间值,判断要找的值和中间值大小的比较。如果中间值大一些,则在中间值的左侧区域继续按照上述方式查找。如果中间值小一些,则在中间值的右侧区域继续按照上述方式查找。直到找到我们希望的…

win7讲述人修复_揭秘:干掉了win7!为何win10屡被吐槽它却“永世留芳”

干掉了win7系统,win10似是更加地“肆无忌惮”了!自微软宣布停止Windows 7的全部支持,而后win7的老用户越发频繁地收到win10的升级通知。要知道,“停止全部支持”也就意味着win7不再有任何新特性,在安全方面也不再能得到…

Ubuntu修改环境变量

修改用户环境变量 用户环境变量通常被存储在下面的文件中: ~/.profile~/.bash_profile 或者 ~./bash_login~/.bashrc上述文件在Ubuntu 10.0以前版本不推荐使用。 系统环境变量 系统环境变量一般保存在下面的文件中: /etc/environment/etc/profile/etc/ba…

Javasript设计模式之链式调用

写过jquery的可能都知道,jquery里面可以很方便的使用以下代码: // 不使用链式调用 const element $(ele); element.addClass(red); element.removeClass(green); element.show();// 链式调用 $(ele).addClass(red).removeClass(green).show(); 而jquery…

实现图片打乱_2020 回顾 | 25张图片,记录潮州的这一年

一年将近,万物更新这一年,不简单,也不容易让我们把时针拨回到1月通过镜头来回顾潮州这一年来令人难忘、激动和高光的时刻// 1月 //- January - 1月份的潮州充满了年味大家都沉浸在迎接新年的喜悦心情中期盼着新年的到来突如其来的疫情打乱了所…