文章出处:http://www.cnblogs.com/wupeiqi/articles/5040823.html

SocketServer内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理多个客户端请求的Socket服务端。即:每个客户端请求连接到服务器时,Socket服务端都会在服务器是创建一个“线程”或者“进程” 专门负责处理当前客户端的所有请求。

ThreadingTCPServer

ThreadingTCPServer实现的Soket服务器内部会为每个client创建一个 “线程”,该线程用来和客户端进行交互。

1、ThreadingTCPServer基础

使用ThreadingTCPServer:

  • 创建一个继承自 SocketServer.BaseRequestHandler 的类
  • 类中必须定义一个名称为 handle 的方法
  • 启动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方法)
import socket
import threading
import selectdef process(request, client_data):print(request, client_data)conn = requestconn.sendall(bytes("Welcom to 10086",encoding='utf-8'))flag = Truewhile flag:data = conn.recv(1024)if data == 'exit':flag = Falseelif data == '0':conn.sendall(bytes("0000",encoding='utf-8'))else:conn.sendall(bytes("Do it again",encoding="utf-8"))
sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sk.bind(('127.0.0.1',9999))
sk.listen(5)while True:r, w, e = select.select([sk,],[], [], 1)print('looping')if sk in r:print("Get request")request, client_address = sk.accept()t = threading.Thread(target=process, args=(request, client_address))t.daemon = Falset.start()
sk.close()

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

ForkingTCPServer

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

基本使用:

服务器端:

import socketserverclass MyServer(socketserver.BaseRequestHandler):def handle(self):# print(self.request, self.client_address, self.server)conn = self.requestconn.sendall(bytes('Welcome to connect 10086',encoding='utf-8'))Flag = Truewhile Flag:data = conn.recv(1024)if data == 'exit':Flag = Falseelif data == '0':conn.sendall(bytes('sssssss',encoding='utf-8'))else:conn.sendall(bytes('do it again',encoding='utf8'))if __name__ == '__main__':server = socketserver.ForkingTCPServer(('127.0.0.1',8009),MyServer)server.serve_forever()

客户端:

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

事件驱动

简而言之,事件驱动分为二个部分:第一,注册事件;第二,触发事件。

自定义事件驱动框架,命名为:“弑君者”:

event_list =[]def run():for event in event_list:obj = event()obj.execute()class BaseHandler(object):def execute(self):raise Exception("You must overwrite execute")

使用方法:

from day9 import sourceclass MyHandler(source.BaseHandler):def execute(self):print("Event-drive execute myhandler")source.event_list.append(MyHandler)
source.run()

如上述代码,事件驱动只不过是框架规定了执行顺序,程序员在使用框架时,可以向原执行顺序中注册“事件”,从而在框架执行时可以出发已注册的“事件”。

基于事件驱动Socket

from twisted.internet import protocol
from twisted.internet import reactorclass Echo(protocol.Protocol):def dataReceived(self, data):self.transport.write(data)def main():factory = protocol.ServerFactory()factory.protocol = Echoreactor.listenTCP(8000, factory)reactor.run()if __name__ == '__main__':main()

程序执行流程:

  • 运行服务端程序
  • 创建Protocol的派生类Echo
  • 创建ServerFactory对象,并将Echo类封装到其protocol字段中
  • 执行reactor的 listenTCP 方法,内部使用 tcp.Port 创建socket server对象,并将该对象添加到了 reactor的set类型的字段 _read 中
  • 执行reactor的 run 方法,内部执行 while 循环,并通过 select 来监视 _read 中文件描述符是否有变化,循环中...
  • 客户端请求到达
  • 执行reactor的 _doReadOrWrite 方法,其内部通过反射调用 tcp.Port 类的 doRead 方法,内部 accept 客户端连接并创建Server对象实例(用于封装客户端socket信息)和 创建 Echo 对象实例(用于处理请求) ,然后调用 Echo 对象实例的 makeConnection 方法,创建连接。
  • 执行 tcp.Server 类的 doRead 方法,读取数据,
  • 执行 tcp.Server 类的 _dataReceived 方法,如果读取数据内容为空(关闭链接),否则,出发 Echo 的 dataReceived 方法
  • 执行 Echo 的 dataReceived 方法

从源码可以看出,上述实例本质上使用了事件驱动的方法 和 IO多路复用的机制来进行Socket的处理。

from twisted.internet import reactor, protocol
from twisted.web.client import getPage
from twisted.internet import reactor
import timeclass Echo(protocol.Protocol):def dataReceived(self, data):deferred1 = getPage('http://cnblogs.com')deferred1.addCallback(self.printContents)deferred2 = getPage('http://baidu.com')deferred2.addCallback(self.printContents)for i in range(2):time.sleep(1)print 'execute ',idef execute(self,data):self.transport.write(data)def printContents(self,content):print len(content),content[0:100],time.time()def main():factory = protocol.ServerFactory()factory.protocol = Echoreactor.listenTCP(8000,factory)reactor.run()if __name__ == '__main__':main()

转载于:https://www.cnblogs.com/william126/p/7203980.html

Python实战之SocketServer模块相关推荐

  1. python中的socketserver模块与多线程

    早就听说socketsever特别厉害,可以简化客户端和服务端的实现,尤其是在多线程socket通话的情境下,可以说是一个比较高级的模块 python下的socket编程我们已经学过了,而今天,我们来 ...

  2. Python实战之logging模块使用详解

    用Python写代码的时候,在想看的地方写个print xx 就能在控制台上显示打印信息,这样子就能知道它是什么了,但是当我需要看大量的地方或者在一个文件中查看的时候,这时候print就不大方便了,所 ...

  3. python网络编程-socketserver模块

    使用socketserver 老规矩,先引入import socketserver 必须创建一个类,且继承socketserver.BaseRequestHandler 这个类中必须重写handle( ...

  4. 学习笔记(03):Python实战编程-sys模块

    立即学习:https://edu.csdn.net/course/play/19711/255505?utm_source=blogtoedu sys是一个系统的环境交互模块,是唯一一个可以与操作系统 ...

  5. 【Python实战】chinesecalendar模块处理中国股市交易日期

    我们知道中国上海证券交易所和深圳证券交易所日常交易日期为星期一到星期五,并且法定节假日不交易. 我们可以通过chinesecalendar模块判断某一天是否为工作日(中国法定工作日,调休的时候有可能周 ...

  6. python socket tcp客户端_python网络编程socketserver模块(实现TCP客户端/服务器)

    摘录python核心编程 socketserver(python3.x版本重新命名)是标准库中的网络编程的高级模块.通过将创建网络客户端和服务器所必须的代码封装起来,简化了模板,为你提供了各种各样的类 ...

  7. python网络编程-异常处理-异常捕获-抛出异常-断言-自定义异常-UDP通信-socketserver模块应用-03

    python网络编程-异常处理-异常捕获-抛出异常-断言-自定义异常-UDP通信-socketserver模块应用-03 参考文章: (1)python网络编程-异常处理-异常捕获-抛出异常-断言-自 ...

  8. python3 socketserver_《Python核心编程(第3版)》——2.5 *SocketServer模块

    本节书摘来自异步社区<Python核心编程(第3版)>一书中的第2章,第2.5节,作者[美] Wesley Chun(卫斯理 春),孙波翔 李斌 李晗 译,更多章节内容可以访问云栖社区&q ...

  9. python socket udp并发_Python进阶----UDP协议使用socket通信,socketserver模块实现并发

    Python进阶----UDP协议使用socket通信,socketserver模块实现并发 一丶基于UDP协议的socket 实现UDP协议传输数据 代码如下:

最新文章

  1. 【转载】Linux 软件安装到 /usr,/usr/local/ 还是 /opt 目录?
  2. 计算机网络实验可变长子网掩码,计算机网络实验3-子网掩码与划分子网实验报告.docx...
  3. Git_学习_06_ 放弃本地修改
  4. requests库怎么安装在python中-python安装requests库的实例代码
  5. 什么是好的API设计?
  6. Email 正则验证
  7. python文件下载器代码_GitHub - applechi/pythonCollection: python代码集合(文件下载器、pdf合并、极客时间专栏下载、掘金小册下载、新浪微博爬虫等)...
  8. 适用于Java开发人员的Elasticsearch:Java的Elasticsearch
  9. chrome稍后阅读功能reading list
  10. Linux操作Oracle(8)——Oracle数据库迁移全纪录(1) — 表空间 用户 权限迁移
  11. Centos7的iso everything与DVD以及Live的区别
  12. canva画图 图片居中裁剪_男士秋裤,一片式补裆款裁剪图分享给大家。天凉该给家人做秋裤啦...
  13. 《C++ AMP:用Visual C++加速大规模并行计算》——3.6 parallel_for_each
  14. python编写登录脚本_python实现的登录和操作开心网脚本分享
  15. 使用matlab计算变上限积分,matlab含有变上限积分参数的非线性回归
  16. java画五角星_java 画五角星 填充五角星
  17. 超越阿里达摩院成绩,这个斯坦福团队用“国产求解器”助中国企业实现智能决策|快公司...
  18. 计算机教师专业技术报告,计算机教师专业技术分析报告
  19. Pyinstaller 生成 exe 及打包资源文件
  20. 北京至桂林amp;amp;阳朔两宅人自助游,有图有

热门文章

  1. VMware Workstation 无法与 Windows XP \ Windows 7 \ Windows 8 进行共享文件夹。
  2. 数据结构上机实践第八周项目6- 猴子选大王(数组版)
  3. java port_Java NonRegisteringDriver.port方法代码示例
  4. qt 提升 全局包含_研讨引思想碰撞,学习促共同提升 | 粤渝两地幼教同行深度交流...
  5. php smarty ci,CI整合Smarty,cismarty_PHP教程
  6. 磁盘不足 导致内存 linux,为什么 Linux 需要 Swapping,仅仅是内存不够用?
  7. python如何查看类信息_关于如何查看本地python类库详细信息的方法
  8. sql avg和count_SQL sum(),count()和avg()函数
  9. 了解C ++中的Vector insert()
  10. Python检查模块