前倾回顾
1.总结进程线程的区别 2.网络通信模型 [1] 循环模型:循环接收请求处理请求,每次同时只能处理一个请求 [2]IO并发模型,可以同时处理多个IO请求 [3]多进程/多线程网络并发:可以互不影响处理多个任务 3.基于fork的多进程并发 4.ftp文件服务模型 ***************************************************** 一.基于threading的多线程网络并发 [1]实现原理:每当一个客户端发起请求,就创建一个新的线程处理客户端具体请求,主线程循环等待处理其他客户端连接。 [2]实现步骤: 1.创建监听套接字 2.循环接收客户端请求连接 3.当有新的客户端连接创建线程处理客户端请求 4.主线程继续等待其他客户端连接 5.当客户端退出,则对应 二.集成模块完成多进程/多线程网并发 1. import sockectserver *通过模块提供的不同的类的组合来完成多进程或者多线程 .tcp 或udp的网路并发模型 2.常用类说明 TCPServer:创建TCP服务端套接字 UDPServer:创建UDP服务端套接字 StreamRequestHandler:处理TCP客户端请求 DatageramRequestHandler:处理udp客户端请求 ForkingMinIn :创建多进程并发 ForkingTCPServer :ForkingMinIn + TCPServer ForkingUDPServer :ForkingMinIn + UDPServer ThreadingMixIn :创建多线程并发 ThreadingTCPServer :ThreadingMixIn + TCPServer ThreadingUDPServer :ThreadingMixIn + UDPServer 3.步骤 1.创建服务器类,通过选择继承的类,决定创建TCP或者UDP, 多进程或者多线程确定定法类型 2.创建请求处理类,根据服务类型选择stream处理类还是Datager处理类。重写handle方法,左具体的请求处理 3. 通过服务器类创建服务器对象,并绑定请求处理类 4.通过富强武器对象,调用server_forever()启动服务 三.HTTPServer v2.0 1.主要功能: 1.接收客户端(浏览器)请求 2.解析客户端发送的请求 3.根据请求组织数据内容 4.将数据内容形参http响应格式返回给浏览器 2.升级点 1.采用多线程并发,可以满足多个客户端同时同时发起请求情况 2.做基本的请求解析,根据具体的请求返回具体内容, 同时满足客户端点单的非网页请求情况 3.通过类接口形式进行功能封装 3.技术点 1.HTTP协议要求数据传输使用tcp套接字 2.httpserver采用多线程并发网络模型 3.类的封装接口 4.http协议的请求和响应格式 http请求: 请求行:GET /abc.html HTTP/1.1 请求头: 空行 请求体http响应:
响应行:HTTP/1.1 200 OK 响应头 空行 响应体:返回的数据内容1 ''' 2 HTTP Server v2.0 3 *多线程并发 4 *基本的request解析 5 *能够反馈基本数据 6 *使用类封装 7 ''' 8 9 from socket import * 10 from threading import Thread 11 import sys 12 13 14 #封装具体的类作为THHP Server功能模块 15 class HTTPServer(object): 16 def __init__(self,server_addr,static_dir): 17 #添加对象属性 18 self.server_address = server_addr#属性 19 self.static_dir = static_dir 20 self.create_socket() 21 self.bind() 22 23 def create_socket(self): 24 self.sockfd = socket() 25 self.sockfd.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) 26 27 def bind(self): 28 self.sockfd.bind(self.server_address) 29 self.ip = self.server_address[0] 30 self.port =self.server_address[1] 31 #启动服务 32 def serve_forever(self): 33 self.sockfd.listen(5) 34 print('Listen the port %d'%self.port) 35 while True: 36 try: 37 connfd,addr = self.sockfd.accept() 38 except KeyboardInterrupt: 39 self.sockfd.close() 40 sys.exit("退出服务器") 41 except Exception as e: 42 print("Error:",e) 43 continue 44 #创建多线程处理请求 45 clientThread = Thread(target = self.handle,args=(connfd,)) 46 clientThread.setDaemon(True) 47 clientThread.start() 48 49 #具体处理thhp请求 50 def handle(self,connfd): 51 #接受HTTP请求 52 request = connfd.recv(4096) 53 #防止浏览器异常断开 54 if not request: 55 connfd.close() 56 return 57 #请求解析 58 requestHeaders = request.splitlines() 59 print(connfd.getpeername(),":",requestHeaders[0]) 60 #获取请求内容 61 getRequest = str(requestHeaders[0]).split(' ')[1] 62 63 if getRequest =='/' or getRequest[-5:]=='.html': 64 self.get_html(connfd,getRequest) 65 else: 66 print("想获取其他内容") 67 connfd.close() 68 69 def get_html(self,connfd,getRequest): 70 if getRequest =='/': 71 filename = self.static_dir + '/manager.html' 72 else: 73 filename =self.static_dir + getRequest 74 try: 75 f = open(filename) 76 except IOError: 77 #没有找到网页 78 responseHeaders = "HTTP/1.1 404 Not Found\r\n" 79 responseHeaders += '\r\n' 80 responseBody = "Sorry,Not found the page" 81 else: 82 #返回网页内容 83 responseHeaders = "HTTP/1.1 200 OK\r\n" 84 responseHeaders +="\r\n" 85 responseBody = f.read() 86 finally: 87 response = responseHeaders + responseBody 88 connfd.send(response.encode())#发给客户端 89 90 def get_data(self,connfd,getRequest): 91 responseHeaders = "HTTP/1.1 200 OK\r\n" 92 responseHeaders += '\r\n' 93 responseBody ="waiting httpserver v3.0
" 94 response = responseHeaders + responseBody 95 connfd.send(response.encode())#发给客户端 96 97 98 if __name__=="__main__": 99 #使用者自己设定ress100 server_addr = ('0.0.0.0',8000)101 #用户提供存放网页的目录102 static_dir ="./static"103 #创富强武器对象104 httpd = HTTPServer(server_addr,static_dir)105 #启动服务106 httpd.serve_forever()107
1 from greenlet import greenlet 2 3 def test1(): 4 print("执行test1") 5 gr2.switch() 6 print("结束test2") 7 gr2.switch() 8 9 def test2(): 10 gr1.switch() 11 print("执行test1") 12 print("结束test2") 13 14 #将函数变为协程 15 gr1 = greenlet(test1) 16 gr2 = greenlet(test2) 17 18 19 #启动协程 20 gr1.switch() #执行协程1
* gevent协程 只有在遇到gevent指定的阻塞行为时才会自动在协程之间进行跳转
如:gevent.joinall(),gevent.sleep()带来阻塞1 import gevent 2 from gevent import spawn 3 4 def foo(): 5 print("Running foo") 6 gevent.sleep(3) 7 print("Foo again") 8 9 def bar(): 10 print("Running bar") 11 gevent.sleep(2) 12 print("Bar again") 13 14 f = gevent.spawn(foo) 15 b = gevent.spawn(bar) 16 gevent.joinall([f,b]) 17 18 # from gevent import spawn,sleep,joinall 19 20 # def foo(): 21 # print("Running foo") 22 # sleep(3) 23 # print("Foo again") 24 25 # def bar(): 26 # print("Running bar") 27 # sleep(2) 28 # print("Bar again") 29 # f = spawn(foo) 30 # b = spawn(bar) 31 # joinall([f,b]) 32
作业:1.梳理之前的项目代码思路
2.复习mysql数据库用法1 ''' 2 HTTP Server v2.0 3 *多线程并发 4 *基本的request解析 5 *能够反馈基本数据 6 *使用类封装 7 ''' 8 9 from socket import * 10 from threading import Thread 11 import sys 12 13 14 #封装具体的类作为THHP Server功能模块 15 class HTTPServer(object): 16 def __init__(self,server_addr,static_dir): 17 #添加对象属性 18 self.server_address = server_addr#属性 19 self.static_dir = static_dir 20 self.create_socket() 21 self.bind() 22 23 def create_socket(self): 24 self.sockfd = socket() 25 self.sockfd.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) 26 27 def bind(self): 28 self.sockfd.bind(self.server_address) 29 self.ip = self.server_address[0] 30 self.port =self.server_address[1] 31 #启动服务 32 def serve_forever(self): 33 self.sockfd.listen(5) 34 print('Listen the port %d'%self.port) 35 while True: 36 try: 37 connfd,addr = self.sockfd.accept() 38 except KeyboardInterrupt: 39 self.sockfd.close() 40 sys.exit("退出服务器") 41 except Exception as e: 42 print("Error:",e) 43 continue 44 #创建多线程处理请求 45 clientThread = Thread(target = self.handle,args=(connfd,)) 46 clientThread.setDaemon(True) 47 clientThread.start() 48 49 #具体处理thhp请求 50 def handle(self,connfd): 51 #接受HTTP请求 52 request = connfd.recv(4096) 53 #防止浏览器异常断开 54 if not request: 55 connfd.close() 56 return 57 #请求解析 58 requestHeaders = request.splitlines() 59 print(connfd.getpeername(),":",requestHeaders[0]) 60 #获取请求内容 61 getRequest = str(requestHeaders[0]).split(' ')[1] 62 63 if getRequest =='/' or getRequest[-5:]=='.html': 64 self.get_html(connfd,getRequest) 65 else: 66 print("想获取其他内容") 67 connfd.close() 68 69 def get_html(self,connfd,getRequest): 70 if getRequest =='/': 71 filename = self.static_dir + '/manager.html' 72 else: 73 filename =self.static_dir + getRequest 74 try: 75 f = open(filename) 76 except IOError: 77 #没有找到网页 78 responseHeaders = "HTTP/1.1 404 Not Found\r\n" 79 responseHeaders += '\r\n' 80 responseBody = "Sorry,Not found the page" 81 else: 82 #返回网页内容 83 responseHeaders = "HTTP/1.1 200 OK\r\n" 84 responseHeaders +="\r\n" 85 responseBody = f.read() 86 finally: 87 response = responseHeaders + responseBody 88 connfd.send(response.encode())#发给客户端 89 90 def get_data(self,connfd,getRequest): 91 responseHeaders = "HTTP/1.1 200 OK\r\n" 92 responseHeaders += '\r\n' 93 responseBody ="waiting httpserver v3.0
" 94 response = responseHeaders + responseBody 95 connfd.send(response.encode())#发给客户端 96 97 98 if __name__=="__main__": 99 #使用者自己设定ress100 server_addr = ('0.0.0.0',8000)101 #用户提供存放网页的目录102 static_dir ="./static"103 #创富强武器对象104 httpd = HTTPServer(server_addr,static_dir)105 #启动服务106 httpd.serve_forever()107