前期准备:

安装python环境
安装pycharm
安装MySQL数据库
安装pymsql
创建一个学生表,存入数据
我们只是实现一个非常简单的web服务,前端页面不会专门做页面文件,会在代码中以具体命令的形式形成文件样式。服务器的功能:

1、show.html显示student表中的数据,点击页面内的修改按钮,会跳转到change.html页面修改内容

2、change.html修改student表中数据,将学生姓名由“张三”改为“李四”,点击页面内的"show page"会重新跳转到显示学生信息页面重新显示修改后的学生信息

创建表

create table student(
id int primary key,
sname varchar(50) not null,
sex char(5) not null
);

  

原始表数据

一、创建tcp服务器tcpWebServer.py

服务器需要实现多线程的访问,采用面向对象的思想,创建一个服务器类。采用wsgi的思想,需要在服务器类中预先设置一个set_response方法,供框架代码中application的调用

Tcp服务器类创建流程如下:

因为多线程中都需要使用到套接字创建、ip和port的绑定,以及监听(listen),所以我们设计类的时候将这几部分设置为对象属性,直接在初始化方法中创建

创建__init__方法

  1. 创建套接字绑定ip和port:使用命令bind()
  2. Listen使套接字变为可以被动链接:使用命令listen()

创建服务器处理请求/发送请求方法

  1. 接收客户端传送的request数据
  2. 因为前端发送的数据是url地址所以需要处理url地址的代码
  3. 设置伪静态的url地址
  4. 发送response返回给前端

创建set_response函数

创建运行函数

 import multiprocessing
import re
import socket
from 简单web服务实现 import web_frame class MSGIServer:
def __init__(self):
"""初始化方法,完成套接字创建、ip和port绑定、listen监听"""
# 创建套接字
self.tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 绑定ip和端口,使用方法bind((ip, 端口)),注意bind方法需要入参一个元组
# 自己编写的代码不要使用1024以内的端口号
self.tcp_socket.bind(('', 7890)) #监听
self.tcp_socket.listen(128) def client_server(self, new_socket):
"""处理和客户端之间数据的交互:接收recv/发送send"""
# 接收客户端发送过来的请求
# 使用方法recv(),数字参数是指定长度
# decode()方法实现解码,参数为编码格式,因为为使用的window系统,所以使用gbk格式
request = new_socket.recv(1024).decode('gbk')
print(str(request).splitlines()[0])
# 使用正则提取请求url地址的后缀名
# group()表示分组匹配
file_name = re.match('.*/.*\.([a-z]*)\sH', str(request).splitlines()[0]).group(1)
# 使用正则提取请求的url地址,用于后面代码中进行匹配
page_name = re.match('.*/(.*)\sH', str(request).splitlines()[0]).group(1)
# 返回数据给客户端
# 根据请求的url地址的不同,返回不同的数据,伪静态(.html)内容是目标内容,否则一律返回404
if not file_name.endswith('html'):
response = "HTTP/1.1 200 OK \r\n"
response += '\r\n'
response += "<h1>404 NOT FOUND</h1>"
new_socket.send(response.encode('gbk'))
else:
# 创建字典,后面调用application函数作为参数传递
env = dict()
env['path'] = page_name
print('--->page_name=%s<---' % page_name)
# 调用框架模块中的application方法,传入url信息,确定执行的命令
body = web_frame.application(env, self.set_response)
# print('--->body=%s<---' % body)
# response = "HTTP/1.1 200 OK \r\n"
header = 'HTTP/1.1 %s\r\n' % self.status
for temp in self.header:
header += '%s:%s' % (temp[0], temp[1])
header += '\r\n'
response = header + '\r\n' + body new_socket.send(response.encode('utf-8'))
new_socket.close() # 设置请求头
def set_response(self, status, headers):
self.status = status
self.header = headers def run_forver(self):
"""实现web服务器"""
while True:
# 4、等待新客户端的链接 accept
new_socket, socket_address = self.tcp_socket.accept()
# 5、为新客户端服务,独立为服务的方法处理接收和发送数据(request\response)
p = multiprocessing.Process(target=self.client_server, args=(new_socket,))
# client_server(new_socket)
p.start()
new_socket.close()
self.tcp_socket.close() def main():
msgi_server = MSGIServer()
msgi_server.run_forver() if __name__ == '__main__':
main()

二、创建框架web_frame.py

  1. 创建闭包
  2. 创建两个函数show(显示学生信息)、change(修改学生信息)
  3. 创建application函数
 import time
import pymysql
import logging URL_FUNC_DICT = dict()
func_list = list() def route(url):
"""创建路由闭包:
实现url地址的路由,即根据装饰器填入的url信息执行装饰器所装饰的方法
"""
def set_func(func):
URL_FUNC_DICT[url] = func def call_func():
func()
return call_func
return set_func @route('show.html')
def show():
"""登录网页"""
sql = "select * from student;"
# 链接MySQL服务器
conn = pymysql.connect(host='127.0.0.1', user='wang', password='', database='jingdong', port=3306, charset='utf8')
cur = conn.cursor()
cur.execute(sql)
# 获取查询到的数据
data = cur.fetchone()
print(data)
cur.close()
conn.close()
# 构建一个网页内容
table = """<html>
<head>
<meta charset="utf-8">
<title>学生信息</title>
</head>
<body>
<tr>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>
<a href="/change.html"><input type="button" value="修改"></a>
</td>
</tr>
</body>
</html>"""
# 将数据库查询到的数据拼接到网页内容中
res = table % (str(data[0]), data[1], data[2])
# return cur.fetchone()[0]+str
return res @route('change.html')
def change():
"""修改数据页面"""
# 链接MySQL服务器
sql = "update student set sname='李四';"
# 创建数据库链接对象
conn = pymysql.connect(host='127.0.0.1', user='wang', password='', database='jingdong', port=3306,
charset='utf8')
# 创建游标
cur = conn.cursor()
# 执行sql命令
lines = cur.execute(sql)
# 提交数据
conn.commit()
cur.close()
conn.close()
return "<a href=\"show.html\">show page</a>" # 服务器代码调用执行的代码
# 遵照wsgi协议,框架中需要存在一个application(字典, 函数引用)函数
# 字典,用来传入前端所提交的信息 引用的函数时服务器创建的封装响应头的函数
def application(environ, start_response):
# 调用tcpWebServer模块中的设置相应函数,设置响应头
start_response('200 OK', [('Context-Type', 'text/html')])
# 获取前端传入的字典中的路径,即url地址
page_name = environ['path']
# 设置日志
logging.basicConfig(level=logging.INFO,
filename='./log.txt',
filemode='a',
# format表示日志文件中显示的格式
# astime时间 写入文件名 第几行的日志信息 日志等级 打印的信息
format='%(asctime)s-%(filename)s[line:%(lineno)d]-%(levelname)s:%(message)s'
)
logging.info('访问的是:%s' % page_name)
if page_name in URL_FUNC_DICT.keys():
return URL_FUNC_DICT[page_name]()
else:
return 'not Found'

运行效果

代码运行,浏览器输入"localhost:7890/show.html"查看学生的信息

点击“修改”按钮会跳转到change.html页面

再点击“show page”链接会重新跳转回show.html页面,显示修改后的学生信息

数据库中的数据也已经同步更新

代码目录下已经生成了日志文件

内容为我们设定的显示内容

以上是一个非常粗糙的web服务,后续我们会使用到Django框架来详细设计一个完整的web服务

WSGI-mini-web框架服务器的更多相关文章

  1. [Python之路] 实现简易HTTP服务器与MINI WEB框架(利用WSGI实现服务器与框架解耦)

    本文描述如果简单实现自定义Web服务器与自定义简易框架,并且不断进行版本迭代,从而清晰的展现服务器与Web框架之间是如何结合.如何配合工作的.以及WSGI是什么. 本文帖的代码有点多,但基本每次迭代修 ...

  2. Wsgi的web框架实例

    建立server服务端: from wsgiref.simple_server import make_server import time def f1(request): return [b'&l ...

  3. [Python之路] 使用装饰器给Web框架添加路由功能(静态、动态、伪静态URL)

    一.观察以下代码 以下来自 Python实现简易HTTP服务器与MINI WEB框架(利用WSGI实现服务器与框架解耦) 中的mini_frame最后版本的代码: import time def in ...

  4. python学习之路web框架

    WEB框架的本质 python的WEB框架分为两大类: 1.自己写socket,自己处理请求 2.基于wsgi(Web Server Gateway Interface WEB服务网关接口),自己处理 ...

  5. 07 返回多个页面web框架

    07 返回多个页面web框架 服务器server端python程序(不同页面版本): import socket server=socket.socket() server.bind(("1 ...

  6. 06 返回静态文件的映射(函数/多线程)web框架

    06 返回静态文件的映射(函数/多线程)web框架 服务器server端python程序(函数版): import socket server = socket.socket() server.bin ...

  7. 05 返回静态文件的多线程web框架

    05 返回静态文件的多线程web框架 服务器server端python程序(多线程版): import socket from threading import Thread,currentThrea ...

  8. 04 返回静态文件的函数web框架

    04 返回静态文件的函数web框架 服务器server端python程序(函数版): import socket server = socket.socket() server.bind((" ...

  9. 03 返回静态文件的高级web框架

    03 返回静态文件的高级web框架 服务器server端python程序(高级版): import socket server=socket.socket() server.bind(("1 ...

  10. 02 初级版web框架

    02 初级版web框架 服务器server端python程序(初级版): import socket server=socket.socket() server.bind(("127.0.0 ...

随机推荐

  1. 奇点云COO刘莹应邀出席《APEC SME大数据与人工智能论坛》

    10月24日-25日,由亚太经合组织(APEC).韩国中小型及初创企业管理局(the Ministry of SMEs & Startups of Korea)主办的「APEC SME 大数据 ...

  2. [LC] 149. Max Points on a Line

    Given n points on a 2D plane, find the maximum number of points that lie on the same straight line. ...

  3. python库之——sklearn

    机器学习库sklearn 官方documentation(资料)中分为不同的部分: 其中我们主要讲User Guide(机器学习算法理论介绍).API(程序实现方法): 一.User Guide ht ...

  4. OSPF 大实验

    实验拓扑如图所示: 公司A网络如实验拓扑所示,请根据如下需求对网络进行部署: 1) 按照拓扑所示配置OSPF多区域,另外R3与R6,R4与R6间配置RIPv2.R1,R2,R3,R4的环回接口0通告入 ...

  5. java 面向对象 购物车

    一个商城包括多个商品.多个用户.拥有销售商品.展示商品和查找商品功能.2)    一个用户拥有一个购物车,购物车具有结算功能.3)    商城具有名称,静态字符串类型4)    用户类是抽象类,两个子 ...

  6. OA|开放获取期刊|掠夺性期刊|DOI|ORCID|图书馆服务|零次文献|信息素质|

    OA|开放获取期刊|掠夺性期刊|DOI|ORCID|图书馆服务|零次文献| 信息检索 信息素质是什么? 信息素质是指一个人的信息需求.信息意识.信息知识.信息道德.信息能力方面的基本素质. Some ...

  7. 部署描述符web.xml

    部署描述符应用场景 需要传递初始参数给ServletContext 有多个过滤器,并要指定调用顺序 需要更改会话超时设置 要限制资源的访问,并配置用户身份验证方式 xsi:schemaLocation ...

  8. 用Gitolite搭建服务器上的Git

    使用git作为版本控制工具,确实非常流行且好用,常用的git代码服务器有Github还是国内的Gitcafe和OSC都是很不错,可以免费存放一些开源的项目代码,对于私人项目,则需要支付一定的费用.同时 ...

  9. 网络健身O2O,能火吗?

       谈到中国想要020的那些项目,总给人一种土豪烧钱的怪异形象,而最终的成败因素也变得简单,也即谁能烧到最后,谁就能称霸市场,可问题在于,前期投入太多,谁也不甘心主动退出,最后,只落得个油尽灯枯.这 ...

  10. 微信小程序配置二

    tabBar 客户端窗口底部的tab页面切换,只能配置最好两个.最多5个tab 属性说明: 属性 类型 必填 默认值 描述 color HexColor 是 tab上的文字默认颜色 selectedC ...