框架一

自定义Web异步非阻塞框架

suosuo.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-#
# __name__ = Web_Framework.server_async.py
# __date__ = 2019/9/3 8:21
# __author__ ='Shi Wei'
# __description__:
# --------------------------------------------------------------
# 服务端
import socket
import select
import re
import time Buffer_size = 1024
backlog = 5 class HttpRequest:
def __init__(self, conn):
self.socket = conn self.header_bytes = b''
self.header_dict = {}
self.body_bytes = b'' self.method = ''
self.url = ""
self.protrol = '' self.initialize() def header_str(self):
return str(self.header_bytes, encoding="utf-8") def initialize(self):
self.recv_data = bytes() while True:
try:
data = self.socket.recv(Buffer_size)
except Exception as e:
data = None
if not data:
break
else:
self.recv_data += data
recv = self.recv_data.split(b'\r\n\r\n', 1)
if len(recv) == 1: # 格式 不正确
self.body_bytes = self.recv_data
else: # 格式正确
self.header_bytes, self.body_bytes = recv
self.initialize_header() def initialize_header(self):
header_list = self.header_str().split("\r\n")
gen = header_list[0].split(" ")
if len(gen) == 3:
self.method, self.url, self.protrol = gen
for header in header_list:
hea = header.split(":", 1)
if len(hea) == 2:
k, v = hea
self.header_dict[k] = v class HttpResponse:
def __init__(self, contennt):
self.content = contennt self.headers = {}
self.cookies = {}
def response(self):
return bytes(self.content, "utf-8") class HttpNotFound(HttpResponse):
def __init__(self):
super(HttpNotFound, self).__init__("404 Not Found!......") class Future:
def __init__(self, callback):
self._ready = False
self.callback = callback
self.value = None def set_result(self, value=None):
self.value = value
self._ready = True @property
def ready(self):
return self._ready class TimeoutFuture(Future):
def __init__(self, timeout, callback = None):
super(TimeoutFuture, self).__init__(callback=callback)
self.timeout = timeout
self.start_time = time.time() @property
def ready(self):
current_time = time.time()
if current_time > self.start_time + self.timeout:
self._ready = True
return self._ready class Panda:
def __init__(self, routers):
self.routers = routers
self.shiwei = []
self.async_request_handler = {}
self.request = None def run(self, host="127.0.0.1", port=9999):
sk = socket.socket() #(2, 1)
sk.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) #(65535, 4) ###
sk.bind((host, port))
sk.setblocking(False)
sk.listen(backlog)
self.shiwei.append(sk)
try:
while True:
rlist, wlist, elist = select.select(self.shiwei, [], [], 0.05)
for r in rlist:
if r == sk:
conn, addr = sk.accept()
conn.setblocking(False)
self.shiwei.append(conn)
else:
res = self.process(r)
if isinstance(res, HttpResponse):
data = res.response()
r.sendall(data)
self.shiwei.remove(r)
r.close()
else:
self.async_request_handler[r] = res self.polling_callback() # 处理 异步请求
except Exception as e:
print("server_socket------->Exception msg=", e)
finally:
sk.close() def polling_callback(self):
del_conn = []
for conn in self.async_request_handler.keys():
future = self.async_request_handler[conn]
if not future.ready:
continue
if future.callback:
res = future.callback(self.request, future)
conn.sendall(res.response())
else:
res = """HTTP/1.1 200 OK\r\nDate: Tue, 03 Sep 2019 01:44:42 GMT\r\n\r\n<html><head><meta charset="UTF-8"></head><body><h1 align="center" style="margin-top: 200px;">shiwei is one Future....<br>callback = None!...</h1></body></html>"""
conn.sendall(bytes(res, encoding="utf-8"))
self.shiwei.remove(conn)
del_conn.append(conn)
conn.close()
for conn in del_conn:
del self.async_request_handler[conn]
del_conn.clear() def process(self, conn):
""" 处理路由系统 和 执行函数"""
self.request = HttpRequest(conn)
result = HttpNotFound()
for route in self.routers:
if re.match(route[0], self.request.url):
func = route[1]
if func:
response = func(self.request)
result = response
break
return result

使用 suosuo 框架 开发 一个小网站

#!/usr/bin/env python
# -*- coding: utf-8 -*-#
# __name__ = Web_Framework.start01.py
# __date__ = 2019/9/3 9:55
# __author__ ='Shi Wei'
# __description__:
# --------------------------------------------------------------
from server_async import Panda from server_async import HttpResponse
from server_async import TimeoutFuture def shi(request):
try:
print("\033[1;31m url=%s--->header_dict=%s\033[0m"%(request.url, request.header_dict))
except Exception as e:
pass
return HttpResponse("the King of Northern!....") def www(request, future):
return HttpResponse("is future callback func ........") def wei(request):
try:
print("\033[1;31m url=%s--->header_dict=%s\033[0m"%(request.url, request.header_dict))
except Exception as e:
pass
return TimeoutFuture(5, callback=www)
# return HttpResponse("is wei func ") routers = [
(r"/shi", shi),
(r'/wei', wei),
] asy = Panda(routers)
asy.run(port = 9999)

框架二

异步非阻塞 server 端

#!/usr/bin/env python
# -*- coding: utf-8 -*-#
# __name__ = Web_Framework.server_suosuo.py
# __date__ = 2019/8/28 19:10
# __author__ ='Shi Wei'
# __description__:
# -------------------------------------------------------------- """ 异步 非 阻塞 Server 端 """ import socket
import select
import time Buffer_size = 1024
class HttpRequest:
def __init__(self, conn):
self.conn = conn
self.recv_data = b''
self.header_bytes = bytes()
self.header_dict = {}
self.body_bytes = bytes() self.method = ""
self.url = ''
self.protocol = "" self.initialize() # 接受 数据 def initialize(self):
while 1:
try:
data = self.conn.recv(Buffer_size)
except Exception as e:
data = None
if not data:
break
else:
self.recv_data += data
continue
temp = self.recv_data.split(b'\r\n\r\n', 1)
if len(temp) == 1: # 代表 是 坏的 client , 格式不正确
self.body_bytes = self.recv_data
else: # 代表 是 好的 client , 格式 正确
header, body = temp
self.header_bytes += header
self.body_bytes += body
self.initialize_headers() # 切割 请求头 数据 @property
def header_str(self):
return str(self.header_bytes, encoding="utf-8") def initialize_headers(self):
header_list = self.header_str.split('\r\n')
first_header = header_list[0].split(' ')
if len(first_header) == 3:
self.method, self.url, self.protocol = first_header
for header in header_list:
hea = header.split(':')
if len(hea) == 2:
k, v = hea
self.header_dict[k] = v def Index(request):
return "is Index Page"
# return "HTTP/1.1 200 OK\r\nDate:Fri, 22 May 2009 06:07:21 GMT\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n" def Main(request):
return " Main Page Hello ......" def All(request):
return " HTTP/1.1 200 OK\r\nDate:Fri, 22 May 2009 06:07:21 GMT\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n<html><head</head><body>shiwei</body></html>" routers = [
("/index$", Index),
('/main$', Main),
('/', All),
] def run(): ip_port = ("127.0.0.1", 80,)
backlog = 5
shiwei = []
sk = socket.socket(2, 1)
sk.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sk.bind(ip_port)
sk.listen(backlog)
shiwei.append(sk) while 1:
rlist, wlist, elist = select.select(shiwei, [], [], 0.05) for r in rlist:
if r == sk:
print('服务端 socket=', r)
conn, addr = sk.accept()
conn.setblocking(False)
shiwei.append(conn)
else:
""" 客户端发来数据 """
print("客户端 socket =",r)
request = HttpRequest(r)
# 1. 请求头中获取url
# 2. 去路由中匹配,获取指定的函数
# 3. 执行函数,获取返回值
# 4. 将返回值 r.sendall(b'alskdjalksdjf;asfd')
import re
flag = False
func = None
print("url=", request.url)
for route in routers:
if re.match(route[0], request.url):
func = route[1]
flag = True
break
if flag:
result = func(request)
r.send(bytes(result, encoding="utf-8"))
shiwei.remove(r)
r.close()
else:
result = "404 Not Page...."
r.send(bytes(result, encoding="utf-8"))
shiwei.remove(r)
r.close()
print("url=%s,--->result=%s" % (request.url, result))
if __name__ == '__main__':
run()

异步 非 阻塞 Client 端

#!/usr/bin/env python
# -*- coding: utf-8 -*-#
# __name__ = Web_Framework.client_suosuo.py
# __date__ = 2019/8/29 8:34
# __author__ ='Shi Wei'
# __description__:
# -------------------------------------------------------------- """ 异步 非 阻塞 Client 端 """
import socket
import select Buffer_size = 1024 class HttpRequest:
def __init__(self, sk, url, host, callback):
self.socket = sk
self.url = url
self.host = host
self.callback = callback def fileno(self):
return self.socket.fileno() class HttpResponse:
def __init__(self,recv_data):
self.recv_data = recv_data self.http_version = ""
self.status_code = ''
self.status_msg = "" self.header_bytes = b''
self.header_dict = {}
self.body_bytes = b''
self.initialize() @property
def header_str(self):
return self.header_bytes.decode("utf-8")
def initialize(self):
data = self.recv_data.split(b'\r\n\r\n', 1)
if len(data) == 1: # 没有分割 , 服务端不按照正常格式发送数据
self.body_bytes = data[0]
else: # 代表分割了, 可能为 ["xxxxxxxx", ''], 按照正常格式
h, b = data
self.header_bytes = h
self.body_bytes = b
self.initialize_header()
def initialize_header(self):
header_list = self.header_str.split("\r\n")
temp = header_list[0].split(" ")
if len(temp) == 3:
ht = temp[0].split('/')
if len(ht) == 2:
self.http_version = ht[1]
self.status_code, self.status_msg = temp[1], temp[2]
for header in header_list:
var = header.split(':')
if len(var) == 2:
k, v = var
self.header_dict[k] = v class AsyncRequest:
def __init__(self):
self.shiwei = []
self.haiyan = []
def add_request(self,url, host, callback):
try:
sk = socket.socket()
sk.setblocking(False)
sk.connect((host, 80))
except Exception as e:
pass
request = HttpRequest(sk, url, host, callback)
self.shiwei.append(request)
self.haiyan.append(request) def run(self):
while 1:
rlist, wlist, elist = select.select(self.shiwei, self.haiyan, self.shiwei, 0.05) for w in wlist:
sendstr = "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n"%(w.url, w.host)
data = sendstr.encode("utf-8")
w.socket.send(data)
self.haiyan.remove(w)
for r in rlist:
recv_data = bytes()
while 1:
try:
data = r.socket.recv(Buffer_size)
except Exception as e:
data = None
if not data:
break
else:
recv_data += data
# print("%s--->%s"%(r.host, str(recv_data, encoding="utf-8")))
response = HttpResponse(recv_data)
r.callback(response)
self.shiwei.remove(r)
if not self.shiwei:
break def f1(response):
print("\033[1;30m 保存到文件中, 接收到的数据为: %s \033[0m"%(str(response.body_bytes, encoding="utf-8"))) def f2(response):
print("\033[1;43m 保存到数据库中,接收到的数据为: %s \033[0m"%(str(response.body_bytes, encoding="utf-8"))) urls = [
# {"url": "/", "host": 'www.baidu.com', "callback": f1},
# {"url": "/", "host": 'www.autohome.com', "callback": f2},
{"url": "/index", "host": '127.0.0.1', "callback": f2},
{"url": "/main", "host": "127.0.0.1", "callback": f1},
] asy = AsyncRequest() if __name__ == '__main__':
for tem in urls:
asy.add_request(**tem)
print(asy.shiwei)
asy.run()

Wupeiqi--Web Framework

自定义 异步 IO 非阻塞框架的更多相关文章

  1. 爬虫之多线程 多进程 自定义异步IO框架

    什么是进程? 进程是程序运行的实例,是系统进行资源分配和调度的一个独立单位,它包括独立的地址空间,资源以及1个或多个线程. 什么是线程? 线程可以看成是轻量级的进程,是CPU调度和分派的基本单位. 进 ...

  2. IO模型--阻塞IO,非阻塞IO,IO多路复用,异步IO

    IO模型介绍: * blocking IO 阻塞IO * nonblocking IO 非阻塞IO * IO multiplexing IO多路复用 * signal driven IO 信号驱动IO ...

  3. python 全栈开发,Day44(IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)

    昨日内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yield,greenlet 遇到IO gevent: 检测到IO,能够使用greenlet实现自动切换,规避了IO阻 ...

  4. {python之IO多路复用} IO模型介绍 阻塞IO(blocking IO) 非阻塞IO(non-blocking IO) 多路复用IO(IO multiplexing) 异步IO(Asynchronous I/O) IO模型比较分析 selectors模块

    python之IO多路复用 阅读目录 一 IO模型介绍 二 阻塞IO(blocking IO) 三 非阻塞IO(non-blocking IO) 四 多路复用IO(IO multiplexing) 五 ...

  5. (IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)

    参考博客: https://www.cnblogs.com/xiao987334176/p/9056511.html 内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yi ...

  6. 简述同步IO、异步IO、阻塞IO、非阻塞IO之间的联系与区别

    POSIX 同步IO.异步IO.阻塞IO.非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下. ...

  7. 同步IO、异步IO、阻塞IO、非阻塞IO之间的联系与区别

    POSIX 同步IO.异步IO.阻塞IO.非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下. ...

  8. IO复用\阻塞IO\非阻塞IO\同步IO\异步IO

    转载:IO复用\阻塞IO\非阻塞IO\同步IO\异步IO 一. 什么是IO复用? 它是内核提供的一种同时监控多个文件描述符状态改变的一种能力:例如当进程需要操作多个IO相关描述符时(例如服务器程序要同 ...

  9. 通俗讲解 异步,非阻塞和 IO 复用

    1. 阅前热身 为了更加形象的说明同步异步.阻塞非阻塞,我们以小明去买奶茶为例. 1.1 同步与异步 同步与异步的理解 同步与异步的重点在消息通知的方式上,也就是调用结果通知的方式. 同步: 当一个同 ...

随机推荐

  1. Git的配置与基本操作

    Git是一个版本控制软件,它可以让我们能够拍摄处于可行状态的项目的快照,修改项目(如实现新功能)后,如果项目不能正常运行,可以恢复到前一个可行状态. 通过使用版本控制,我们可以无忧无虑的改进项目,不用 ...

  2. Spring动态数据源-AbstractRoutingDataSource

    在分库分表的情况下,在执行SQL时选择连接不同的数据源(库)的思路:配置多个数据源加到动态数据源对象中,根据实际的情况动态切换到相应的数据源中. 如存放订单信息的有10个库,每个库中有100张表,根据 ...

  3. 程序猿看了要xiao了

    一. 程序猿问科比:“你为什么这么成功? ”科比:“你知道洛杉矶凌晨四点是什么样子吗? ”程序猿:“知道,一般那个时候我还在写代码,怎么了?”科比:“额…….” 二. 女神:你能让这个论坛的人都吵起来 ...

  4. [转]Html.DropDownList()的用法 ( Asp.Net MVC)

    Html.DropDownList()赋默认值: 页面代码如下: <% List<SelectListItem> list = new List<SelectListItem& ...

  5. 手动ubuntu 18.04修改登录锁屏界面效果(含登录背景修改)flat-remix

    前言 在ubuntu 18.04,可以通过修改/etc/alternatives/gdm3.css来进行修改 本来想直接使用flat-remix主题,但是只有这个登录界面没有达到作者演示的效果,所以手 ...

  6. Jenkins slave-agent.jnlp运行无反应

    在配置Jenkins的Windows节点时候,点击slave-agent.jnlp选择javaws.exe运行无反应,cmd命令执行javaws slave-agent.jnlp也不行,slave-a ...

  7. s6tu

    # -*- coding: utf-8 -*- # @Time : 2018/03/30 15:20 # @Author : cxa # @File : liuuchnagtu.py # @Softw ...

  8. scrapy抓取企业名录

    我们要用scrapy抓取企业名录网站的企业信息,并且保存在mysql数据库中,数据大概是22万条,我们用scrapy抓取. 第一步,现在item中定义好要抓取的字段 import scrapy cla ...

  9. php函数名后冒号+数据类型(返回值类型限制/php新特性)

    在PHP7,一个新的功能,返回类型声明已被引入.返回类型声明指定的一个函数返回值的类型. int float bool string interfaces array callable 对象实例 如下 ...

  10. 牛客提高D6t1 积木大赛

    分析 每次修改用二位差分记录一下 之后对于三维分别统计即可 代码 #include<iostream> #include<cstdio> #include<cstring ...