标签:文件 继承 信息 while lag daemon 派生类 overwrite 循环
文章出处:http://www.cnblogs.com/wupeiqi/articles/5040823.html
SocketServer内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理多个客户端请求的Socket服务端。即:每个客户端请求连接到服务器时,Socket服务端都会在服务器是创建一个“线程”或者“进程” 专门负责处理当前客户端的所有请求。
ThreadingTCPServer
ThreadingTCPServer实现的Soket服务器内部会为每个client创建一个 “线程”,该线程用来和客户端进行交互。
1、ThreadingTCPServer基础
使用ThreadingTCPServer:
内部调用流程为:
import socket import threading import select def process(request, client_data): print(request, client_data) conn = request conn.sendall(bytes("Welcom to 10086",encoding=‘utf-8‘)) flag = True while flag: data = conn.recv(1024) if data == ‘exit‘: flag = False elif 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 = False t.start() sk.close()
如精简代码可以看出,SocketServer的ThreadingTCPServer之所以可以同时处理请求得益于 select 和 Threading 两个东西,其实本质上就是在服务器端为每一个客户端创建一个线程,当前线程用来处理对应客户端的请求,所以,可以支持同时n个客户端链接(长连接)。
ForkingTCPServer
ForkingTCPServer和ThreadingTCPServer的使用和执行流程基本一致,只不过在内部分别为请求者建立 “线程” 和 “进程”。
基本使用:
服务器端:
import socketserver class MyServer(socketserver.BaseRequestHandler): def handle(self): # print(self.request, self.client_address, self.server) conn = self.request conn.sendall(bytes(‘Welcome to connect 10086‘,encoding=‘utf-8‘)) Flag = True while Flag: data = conn.recv(1024) if data == ‘exit‘: Flag = False elif 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 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()
事件驱动
简而言之,事件驱动分为二个部分:第一,注册事件;第二,触发事件。
自定义事件驱动框架,命名为:“弑君者”:
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 source class 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 reactor class Echo(protocol.Protocol): def dataReceived(self, data): self.transport.write(data) def main(): factory = protocol.ServerFactory() factory.protocol = Echo reactor.listenTCP(8000, factory) reactor.run() if __name__ == ‘__main__‘: main()
程序执行流程:
从源码可以看出,上述实例本质上使用了事件驱动的方法 和 IO多路复用的机制来进行Socket的处理。
from twisted.internet import reactor, protocol from twisted.web.client import getPage from twisted.internet import reactor import time class 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 ‘,i def 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 = Echo reactor.listenTCP(8000,factory) reactor.run() if __name__ == ‘__main__‘: main()
标签:文件 继承 信息 while lag daemon 派生类 overwrite 循环
原文地址:http://www.cnblogs.com/william126/p/7203980.html