socketserver 源码剖析【有图有真相】:

(一)、Socketserver 内部流程调用图:
  
 
  详解:
 1、self.RequestHandlerClass() = MyClass() 转换为 执行这个方法 class MyClass(socketserer.BaseRquestHandler)。

    


 2、 myclass 没有构造方法 __init__( ),从socketserer.BaseRquestHandler 父类 开始找,有构造函数 __init__( ),并且执行了一个 self.handle()方法 。
    但是,还得从myclass() 类中开始找,即:class MyClass(socketserver.BaseRequestHandler):
                                                   def handle(self): # self = obj创建的实例化。 
    

   
    





################# 精简版的 socketserver 源码剖析 #################
#!/usr/bin/env python
# 详见老师分析:s13期。socketserver 源码分析剖析(一)和(二)。

import socketserver

class MyClass(socketserver.BaseRequestHandler):

def handle(self): #self = obj创建的实例化。
pass

obj = socketserver.ThreadingTCPServer(('127.0.0.1', 9999), MyClass)
obj.serve_forever()

# 原理剖析:窥一斑见全豹
# 创建socket对象
# accept --
# server_address = ('127.0.0.1', 9999)
# RequestHandlerClass = MyClass == ()
# self.RequestHandlerClass() = MyClass() == 执行自己的handle()
# 1、obj封装了 self.RequestHandlerClass = MyClass
# 2、创建了socket,bind,listen


# 1、首先执行构造方法 __init__(),当所有的构造方法执行完了,意味着 实例化完成了,即 obj = socketserver.ThreadingTCPServer()
# 2、遇到执行方法self.函数名(),然后在从头开始找执行。详见:s13 day10 socketserver() 源码分析二。







 2、ThreadingTCPServer源码剖析.

学会看源码非常重要!不能仅仅光会用!大赞~ 知道他的过程和实现~ 怎么学会看源码呢?多看然后画类图,如上图!!!

在理解的时候可以把他们想象为,把所有需要用的方法,都抓到ThreadingTCPServer

内部调用流程为:

  • 启动服务端程序.
  • 执行 TCPServer.__init__ 方法,创建服务端Socket对象并绑定 IP 和 端口
  • 执行 BaseServer.__init__ 方法,将自定义的继承自SocketServer.BaseRequestHandler 的类 MyRequestHandle赋值给 self.RequestHandlerClass
  • 执行 BaseServer.server_forever 方法,While 循环一直监听是否有客户端请求到达 ...
  • 当客户端连接到达服务器
  • 执行 ThreadingMixIn.process_request 方法,创建一个 “线程” 用来处理请求
  • 执行 ThreadingMixIn.process_request_thread 方法
  • 执行 BaseServer.finish_request 方法,执行 self.RequestHandlerClass()
  • 即:执行 自定义 MyRequestHandler 的构造方法(自动调用基类BaseRequestHandler的构造方法,在该构造方法中又会调用 MyRequestHandler的handle方法)

精简源码:

模拟Socekt Server的简化版本:



import socket
import threading
import select

def process(request, client_address): #模拟定义的handle()方法,这个方法内的代码是socket server与Client端交互代码
print (request,client_address)
conn = request
conn.sendall('欢迎致电 10086,请输入1xxx,0转人工服务.')
flag = True
while flag:
data = conn.recv(1024)
if data == 'exit':
flag = False
elif data == '0':
conn.sendall('通过可能会被录音.balabala一大推')
else:
conn.sendall('请重新输入.')

sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sk.bind(('127.0.0.1',8002))
sk.listen(5)

while True: #这里一个while循环循环监控sk文件句柄
r, w, e = select.select([sk,],[],[],1)
print ('looping')
if sk in r: #当sk文件句柄发生变化的时候说明是新的客户端连接过来了
print ('get request')
request, client_address = sk.accept()
t = threading.Thread(target=process, args=(request, client_address)) #创建一个线程,并调用自己定义的process方法执行~然后样客户端与之交互
t.daemon = False
t.start()

sk.close()

如精简代码可以看出,SocketServerThreadingTCPServer之所以可以同时处理请求得益于 select 和 Threading 两个东西,其实本质上就是在服务器端为每一个客户端创建一个线程,当前线程用来处理对应客户端的请求,所以,可以支持同时n个客户端链接(长连接)。


  • ForkingTCPServer 

       ForkingTCPServerThreadingTCPServer的使用和执行流程基本一致,只不过在内部分别为请求者建立 “线程”  和 “进程”。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socketserver

class MyServer(socketserver.BaseRequestHandler):

def handle(self):
# print self.request,self.client_address,self.server
conn = self.request
conn.sendall('欢迎致电 10086,请输入1xxx,0转人工服务.')
Flag = True
while Flag:
data = conn.recv(1024)
if data == 'exit':
Flag = False
elif data == '0':
conn.sendall('通过可能会被录音.balabala一大推')
else:
conn.sendall('请重新输入.')

if __name__ == '__main__':
server = socketserver.ForkingTCPServer(('127.0.0.1',8009),MyServer)
server.serve_forever()



client 

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import socket

ip_port = ('127.0.0.1',8009)
sk = socket.socket()
sk.connect(ip_port)
sk.settimeout(5)

while True:
data = sk.recv(1024)
print ('receive:',data)
inp = input('please input:')
sk.sendall(inp)
if inp == 'exit':
break

sk.close()

client


以上ForkingTCPServer 只是将 ThreadingTCPServer 实例中的代码:

server = SocketServer.ThreadingTCPServer(('127.0.0.1',8009),MyRequestHandler)
变更为:
server = SocketServer.ForkingTCPServer(('127.0.0.1',8009),MyRequestHandler)







socketserver 源码剖析:的更多相关文章

  1. 自己实现多线程的socket,socketserver源码剖析

    1,IO多路复用 三种多路复用的机制:select.poll.epoll 用的多的两个:select和epoll 简单的说就是:1,select和poll所有平台都支持,epoll只有linux支持2 ...

  2. socketserver源码剖析

    作者:人世间链接:https://www.jianshu.com/p/357e436936bf來源:简书简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处 BaseServer 和 B ...

  3. 第二十四篇、socketserver源码剖析

    这里选择的是python2.7(python3和2.7的源码基本类似) #!/usr/bin/env python # -*- coding:utf-8 -*- import SocketServer ...

  4. socket_server源码剖析、python作用域、IO多路复用

    本节内容: 课前准备知识: 函数嵌套函数的使用方法: 我们在使用函数嵌套函数的时候,是学习装饰器的时候,出现过,由一个函数返回值是一个函数体情况. 我们在使用函数嵌套函数的时候,最好也这么写. def ...

  5. Appuim源码剖析(Bootstrap)

    Appuim源码剖析(Bootstrap) SkySeraph Jan. 26th 2017 Email:skyseraph00@163.com 更多精彩请直接访问SkySeraph个人站点:www. ...

  6. python基础-11 socket,IO多路复用,select伪造多线程,select读写分离。socketserver源码分析

    Socket socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. sock ...

  7. jQuery之Deferred源码剖析

    一.前言 大约在夏季,我们谈过ES6的Promise(详见here),其实在ES6前jQuery早就有了Promise,也就是我们所知道的Deferred对象,宗旨当然也和ES6的Promise一样, ...

  8. Nodejs事件引擎libuv源码剖析之:高效线程池(threadpool)的实现

    声明:本文为原创博文,转载请注明出处. Nodejs编程是全异步的,这就意味着我们不必每次都阻塞等待该次操作的结果,而事件完成(就绪)时会主动回调通知我们.在网络编程中,一般都是基于Reactor线程 ...

  9. Apache Spark源码剖析

    Apache Spark源码剖析(全面系统介绍Spark源码,提供分析源码的实用技巧和合理的阅读顺序,充分了解Spark的设计思想和运行机理) 许鹏 著   ISBN 978-7-121-25420- ...

随机推荐

  1. hive2.1.1配置

    hive2.1.1配置 首先在conf下复制hive-site.xml <property> <name>javax.jdo.option.ConnectionURL</ ...

  2. 批量上传文件到HDFS的Shell脚本

    在做Hadoop数据挖掘项目的时候,我们第一步是源数据的获取,即把相应的数据放置到HDFS中,以便Hadoop进行计算,手动将文件上传到HDFS中,未免太费时费力,所以我们可以采取像Flume一样的框 ...

  3. 磁盘 & 文件系统

    1. dumpe2fs –h /dev/sda1 查询整个磁盘情况( 其中后边的设备名可以换 ) 2. df –h , du –h 查询磁盘容量情况 3. 实体链接和符号链接 实体链接: ln mk. ...

  4. Linux设备驱动程序学习之分配内存

    内核为设备驱动提供了一个统一的内存管理接口,所以模块无需涉及分段和分页等问题. 我已经在第一个scull模块中使用了 kmalloc 和 kfree 来分配和释放内存空间. kmalloc 函数内幕 ...

  5. EasyUI简单CRUD

    <!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head>    < ...

  6. 在ChemDraw中输入千分号的方法

    很多的用户都会使用ChemDraw化学绘图工具来绘制一些化学反应的过程,但是一些化合物中有些元素所占的比例是非常小的,这个时候往往就需要千分号来显示比例.但是在ChemDraw的工具栏上只有百分号没有 ...

  7. JavaScript格式化日期输出

     JavaScript Code  12345678910111213141516171819202122232425262728   <script>     window.onload ...

  8. Angular2 初识

    AppComponent 壳的三个实现文件: app.component.ts— 组件的类代码,这是用 TypeScript 写的. app.component.html— 组件的模板,这是用 HTM ...

  9. nginx https配置+nginx跳转到万网虚拟主机

    server { listen 443 ssl; server_name www.104dh.com 104dh.com; ssl on; ssl_certificate cert104/152678 ...

  10. 【原】eclipse使用技巧之代码编辑器分隔窗口

    相信很多使用Intellj IDE的朋友对其split screen功能赞赏有加!其实在eclipse中也可以方便地代码编辑多windows.多views!但是隐藏的有点深,很多朋友不常用到,甚至以为 ...