1. 使用web底层socket的方式实现简易服务器的搭建,用来理解学习

# 1、导入socket模块
import socket
import re
import gevent
import sys
# 破解,让gevent 识别耗时操作
from gevent import monkey
monkey.patch_all()
import Application class HttpServer(object): # 用来初始化 套接字
def __init__(self, port): # 2、创建tcp套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 3、设置地址重用
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 4、绑定端口
tcp_server_socket.bind(("", port))
# 5、设置监听,最大允许客户端连接数128(套接字有主动变为被动)
tcp_server_socket.listen(128)
# 套接字,保存实例属性中
self.tcp_server_socket = tcp_server_socket # 启动Web服务器,并且接受客户端连接
def start(self):
# 6、等待客户端连接(能够接受多个客户端连接)
while True:
# 7、定义函数,实现客户端信息接收和响应
new_client_socket, ip_port = self.tcp_server_socket.accept()
print("[新客户端来了]:", ip_port)
# request_handler(new_client_socket)
g1 = gevent.spawn(self.request_handler, new_client_socket)
# 因为接收客户端链接使用的是While True 死循环,主线程不会退出,协程一定会执行完毕
# g1.join() def request_handler(self, new_client_socket): # ​ 8、接收浏览器请求,并判断请求是否为空
recv_data = new_client_socket.recv(1024)
if not recv_data:
print("浏览器可能已经关闭!~")
new_client_socket.close()
return
# 把接受的内容解码
request_text = recv_data.decode()
# 根据\r\n 拆分字符串,目的:得到第一行
request_list = request_text.split("\r\n")
# request_list[0] 就是我们的请求行
# print(request_list[0])
ret = re.search(r"\s(.*)\s", request_list[0])
# 判断报文是否有误
if not ret:
print("浏览器请求的报文格式错误!")
new_client_socket.close()
return # 获取路径
path_info = ret.group(1)
# print(path_info)
# 访问默认的页面
if path_info == "/":
path_info = "/index.html"
# ​ 9、拼接响应报文 # 判断如果是动态资源 交给框架处理
if path_info.endswith(".html"):
# 字典存储 用户的请求信息
env = {
"PATH_INFO": path_info
} status, headers, response_body = Application.app(env) # 使用框架返回的数据拼接响应报文
response_line = "HTTP/1.1 %s\r\n" % status response_header = ""
for header in headers:
response_header += "%s: %s\r\n" % header response_data = response_line + response_header + "\r\n" + response_body
new_client_socket.send(response_data.encode())
new_client_socket.close()
# 否则认为是静态资源
else:
# 9.2 响应头
response_header = "Server:PythonWS1.0\r\n"
# 9.3 空行
response_blank = "\r\n"
# 9.4 响应体
# response_content = "HelloWorld!\r\n"
# 打开文件,并且读取内容,然后把读取的内容返回给客户端 try:
with open("static"+path_info, "rb") as file:
# response_content 是二进制类型
response_content = file.read()
except Exception as e:
# 9.1 相应行
response_line = "HTTP/1.1 404 Not Found\r\n"
response_content = "Error ! %s" % str(e)
# 对返回的内容进行编码
response_content = response_content.encode()
else:
# 9.1 相应行
response_line = "HTTP/1.1 200 OK\r\n"
finally:
# ​ 10、定义变量保存响应报文内容
response_data = (response_line + response_header + response_blank).encode() + response_content
# ​ 11、发送响应报文给客户端浏览器
new_client_socket.send(response_data) # ​ 12、关闭此次连接的套接字
new_client_socket.close() def main(): # sys.argv 可以获取终端启动程序的时候的启动参数
# sys.argv 返回一个列表,列表中依次保存我们输入的参数内容
# print(sys.argv)
if len(sys.argv) != 2:
print("服务器启动失败,参数的格式:python3 HttpServer.py 端口号")
return # 判断端口号,不能是一个字符串,应该是纯数字
if not sys.argv[1].isdigit():
print("服务器启动失败,端口号应该是纯数字!")
return
# 获取端口号
port = int(sys.argv[1]) # 实例化 HttpServer 对象
httpserver = HttpServer(port) # 启动服务器
httpserver.start() if __name__ == '__main__': main()
2. 建立子应用app用来接收请求 """web框架 web应用程序"""
import time def get_time():
"""当用户请求/gettime.html执行当前方法"""
return time.ctime() def index():
"""当用户请求/index.html 执行"""
# 1 读取模板文件
with open("template/index.html") as file:
html_data = file.read() # 2 查询数据库
data_from_mysql = "have fun" # 3 使用从数据库中查询出来的数据 替换 模板变量
html_data = html_data.replace("{%content%}", data_from_mysql) return html_data def center():
"""当用户请求/center.html 执行"""
# 1 读取模板文件
with open("template/center.html") as file:
html_data = file.read() # 2 查询数据库
data_from_mysql = "have fun" # 3 使用从数据库中查询出来的数据 替换 模板变量
html_data = html_data.replace("{%content%}", data_from_mysql) return html_data # 路由列表 django框架添加路由的方式
route_list = [
('/gettime.html', get_time),
('/center.html', center),
('/index.html', index)
] def app(env):
# 接收 取出用户的信息
path_info = env['PATH_INFO']
print("接收到用户的动态资源请求 %s" % path_info)
# if path_info == '/gettime.html':
# # 状态 响应头 响应体
# return '200 OK', [('Server', 'PWS5.0')], get_time()
# elif path_info == '/index.html':
# return '200 OK', [('Server', 'PWS5.0')], index()
# elif path_info == '/center.html':
# return '200 OK', [('Server', 'PWS5.0')], center()
# 将用户请求路径 和 路由列表中每一个进行比较 如果一致 就执行对应的函数代码
for path, func in route_list:
if path_info == path:
return '200 OK', [('Server', 'PWS5.0')], func()
else:
# 状态 响应头 响应体
return '404 Not Found',[('Server', 'PWS5.0')],"response body from app"

搭建简易的WebServer(基于pyhton实现简易Web框架 使用socket套接字)的更多相关文章

  1. koa : Express出品的下一代基于Node.js的web框架

    https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/001434501579966a ...

  2. 09 基于模块wsgiref版web框架

    09 基于模块wsgiref版web框架 模块引入 真实开发中的python web程序,一般会分为两部分:       服务器程序:负责对socket服务器进行封装,并在请求到来时,对请求的各种数据 ...

  3. [网络编程之Socket套接字介绍,套接字工作流程,基于TCP协议的套接字程序]

    [网络编程之Socket套接字介绍,套接字工作流程,基于TCP协议的套接字程序] 为何学习socket套接字一定要先学习互联网协议: 1.首先:要想开发一款自己的C/S架构软件,就必须掌握socket ...

  4. (网络编程)基于tcp(粘包问题) udp协议的套接字通信

    import   socket 1.通信套接字(1人1句)服务端和1个客户端 2.通信循环(1人多句)服务端和1个客户端 3.通信循环(多人(串行)多句)多个客户端(服务端服务死:1个客户端---&g ...

  5. 基于TCP的socket套接字的网络编程(客户端/服务端模式)

    于数据完整性要求较高的场合,就应采用TCP协议. IP网络层提供IP寻址和路由.因为在网络上数据可以经由多条线路到达目的地,网络层负责找出最佳的传输线路. IP地址与数据包: IP层就是把数据分组从一 ...

  6. 基于servlet实现一个web框架

    servlet作为一个web规范.其本身就算做一个web开发框架,可是其web action (响应某个URI的实现)的实现都是基于类的,不是非常方便,而且3.0之前的版本号还必须通过web.xml配 ...

  7. 基于TCP协议的socket套接字编程

    目录 一.什么是Scoket 二.套接字发展史及分类 2.1 基于文件类型的套接字家族 2.2 基于网络类型的套接字家族 三.套接字工作流程 3.1 服务端套接字函数 3.2 客户端套接字函数 3.3 ...

  8. 基于TCP连接的socket套接字编程

    基于TCP协议的套接字编程(简单) 服务端 import socket server = socket.socket() server.bind( ('127.0.0.1', 9999) ) serv ...

  9. 基于socketserver实现并发的socket套接字编程

    一.基于TCP协议 基于tcp的套接字,关键就是两个循环,一个链接循环,一个通信循环 socketserver模块中分两大类:server类(解决链接问题)和request类(解决通信问题) 1.1 ...

随机推荐

  1. Java Serializable的使用和transient关键字使用小记(转载)

    一:Serializable 1.持久化的简单介绍: “持久化”意味着对象的“生存时间”并不取决于程序是否正在执行——它存在或“生存”于程序的每一次调用之间.通过序列化一个对象,将其写入磁盘,以后在程 ...

  2. oracle常用函数案例

    --INSTR函数 SELECT INSTR(' HELLO WORLD','H') FROM DUAL; --LTRIM RTRIM函数 SELECT LTRIM('*HELLO=','*') FR ...

  3. 取消 Vue 中格式编译警告

    使用VS Code在学习 Vue 的过程中,博主是在2.0之后开始学习的,在写项目的时候发现控制台经常会报一大堆的警告,都是关于格式的,有时候少空格,有时候多空格,不胜其烦,出现这个问题是因为在初始化 ...

  4. class面向对象-2

    hasattr/getattr/setattr/delattr #通过字符串判断/获取/新增/删除对象属性或方法 class att(object): def __init__(self,var): ...

  5. Gevent 性能和 gevent.loop 的运用和带来的思考

    知乎自己在底层造了非常多的轮子,而且也在服务器部署方面和数据获取方面广泛使用 gevent 来提高并发获取数据的能力.现在开始我将结合实际使用与测试慢慢完善自己对 gevent 更全面的使用和扫盲. ...

  6. 搞了一下午时间全浪费在这了,其实是自己拷贝了patch文件,导致tab变成了空格的错

    很老实的基于最新的kernel,源文件,修改了代码.通过diff -uNr --show-c-function dir1 dir2 > ipv6.patch制作了patch文件,准备代码上库构建 ...

  7. jenkins插件findbugs+pmd+checkstyle结合sonar与maven(java环境代码质量和代码规范管理)

    一.下载jdk并安装(最好jdk官网下载解压安装的) 二.下载maven并安装maven 三.安装jenkins及插件 安装checkstyle.pmd.findbugs.maven.sonar等相关 ...

  8. zookeeper客户端操作

    ZooKeeper客户端 zkCli.sh 节点的增删改查 在 bin 目录下的  zkCli.sh  就是ZooKeeper客户端 ./zkCli.sh -timeout 5000  -server ...

  9. Real-time chart using ASP.NET Core and WebSocket

    Solution in glance The following diagram illustrates our solution where IoT device reports readings ...

  10. H5 history.pushState 在微信内修改url后点击用safari打开/复制链接是修改之前的页面

    解决方案:url参数增加随机参数 function wxRefresh() { var replaceQueryParam = (param, newval, search) => { var ...