当前位置: 代码迷 >> 综合 >> mini—web搭建
  详细解决方案

mini—web搭建

热度:7   发布时间:2023-12-03 10:19:41.0

mini—web搭建

各位 想学python的小伙伴 上篇文章我讲到了循环 不知道大家学习的怎么样 有没有不懂的地方啊 我这边可能人气太低了 也没有小伙伴评论和我交流 那今天我就不往下讲了 今天给大家像一个比较有意思的 东西 就是标题上写的 mini——web的搭建 相信大家看完我这篇文章 也能够搭建出属于自己的服务。 好了 话不多说 咱们进入今天的主题

**

python搭建服务端

**
在python中搭建服务端框架 是一件特别容易的事情
细分的话一共也就是7个步骤
1、导入网络模块工具 socket
2、创建服务端连接对象
3、绑定IP地址和端口 方便后续监听是否有客户端请求服务端的ip和端口
4、指定监听数量
5、等待客户端连接
6、接收客户端传递的数据
7、返回数据给客户端
8、关闭服务端

理清步骤以后我们来上代码看一下

#导入网络模块
import socket#创建服务端连接对象 AF_INET指定IP地址类型 IPV4 SOCK_STREAM 表示传输协议 TCP协议
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#绑定IP地址和端口 这里传入得地址是你自己的ip地址
# 端口号是建议端口号设置在8000到9999 它们是以元组的方式传入的
server.bind(('127.0.0.1',8080))# 指定监听数量 自己电脑测试5个就管够了 最多不要超过128
server.listen(5)
#这里在你运行以后打印一下 告诉你 服务端启动了
print('服务端启动')# 4、等待客户端连接 (阻塞) 为什么要加阻塞呢 这个步骤就相当于是一个阻塞函数 这里不接收到值 程序时不往下执行的
#clien,addr 是变量名 随意定义
#代码执行到此 说明连接建立成功
clinet_sockt, addr = server.accept()
print('客户端socket', clinet_sockt)
print('客户端地址', addr)
#接收客户端发来的数据 接收的字节为1024
recv_data = clinet_sockt.recv(1024)
#获取接收数据的长度
recv_data_len = len(recv_data)
#对二进制数据进行解码
recv_count = recv_data.decode('gbk')
print('接收客户端数据为',recv_count)#返回数据给客户端
#这里的clien 是上面等待客户端连接指令里面的客户端信息
data = 'hello python'
clinet_sockt.send(data.encode('gbk'))
#关闭服务端
server.close()

这里如果大家复制粘贴 运行过后 你们应该会发现一个问题 程序只能运行一次 接收一次值 很麻烦 真实的生产场景中 服务器总是源源不断的接收客户端发过来的请求 那怎么样去实现呢 不知道大家还记不记得 我一篇文章中的讲到的死循环 我们利用死循环 让服务端不断地去运行 交给线程去处理
上个代码

#导入网络开发工具
import socket
import threading
''' 1、创建服务端连接对象 2、绑定ip和端口 方便后续监听是否有客户端请求服务端的ip和端口 3、指定监听的数量 4、等待客户端连接 (阻塞) 5、接收客户端传递的数据 6、返回数据给客户端 7、关闭服务端服务端持续运行 需要将while循环 可以将 客户端处理封装成函数 在创建线程处理'''
#封装处理客户端的方法
def client_data(clinet_sockt):while True:# 5、接收客户端传递的数据recv_data = clinet_sockt.recv(1024)# print(recv_data)# 6、返回数据给客户端data = 'hello client'clinet_sockt.send(data.encode('gbk'))# 1、创建服务端连接对象
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 2、绑定ip和端口 方便后续监听是否有客户端请求服务端的ip和端口
server.bind(('192.168.14.48',8006))
# 3、指定监听的数量
server.listen(5)
print('服务端启动.......')
#让服务端持续接收客户端请求的数据
while True:# 4、等待客户端连接 (阻塞)clinet_sockt,addr = server.accept()print('客户端socket',clinet_sockt)print('客户端地址',addr)#创建线程处理客户的请求数据t = threading.Thread(target=client_data,args=(clinet_sockt,))t.start()
# 7、关闭服务端
# server.close()

这里有好多的东西都没有讲 大家就先运行这玩儿一玩儿
像函数 网络协议(TCP HTTP) 线程 都没有给大家讲 大家就先对这些代码 先混个脸熟

给大家弄一个客户端的后台代码

#导入开发工具import socket''' 1、创建socket对象 2、连接服务器 3、发送数据 4、接收服务端返回数据 5、关闭客户端 '''
# 1、创建socket对象 socket.AF_INET 指定ip地址为IPV4,socket.SOCK_STREAM指定通讯协议为TCP协议
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)# 2、连接服务器 (元组)
client.connect(('127.0.0.1',8080))
# 3、发送数据 b'hello server' 直接按照bytes类型传递数据
#将字符串转换为 bytes类型 data.encode()
data = '123.txt'
client.send(data.encode('gbk'))
# 4、接收服务端返回数据 recv(1024)需要指定接受数据的大小
#将bytes类型转换为字符串 str_data = recv_data.decode()
recv_data = client.recv(1024)
str_data  = recv_data.decode('gbk')
print(str_data)
# 5、关闭客户端
client.close()

在放一个HTTP服务器的代码
这里会涉及到 请求报文和 响应报文 对于请求的字符切割 我们后续慢慢的来讲这些东西

import  socket#创建socket
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#绑定ip和端口
server.bind(('192.168.14.50',8080))
#指定监听数量
server.listen(5)
print('服务器启动......')
#等待连接
clint_socket,addr = server.accept()
#获取客户端数据
recv_data = clint_socket.recv(1024)
#将bytes转化为字符串
print('客户端数据:',recv_data.decode())
#返回数据给客户端
send_data = 'hello python'# 构建响应报文
#响应行
response_line ='HTTP/1.1 200 ok \r\n'
#响应头
response_header = 'Server:python\r\n\r\n'
#响应体
response_body = send_data
#拼接三部分数据构成完整的响应报文
response_data = response_line + response_header + response_bodyclint_socket.send(response_data.encode())

Web静态服务器

import  socket#创建socket
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#绑定ip和端口
server.bind(('192.168.14.50',8081))
#指定监听数量
server.listen(5)
print('服务器启动......')
while True:#等待连接clint_socket,addr = server.accept()#获取客户端数据recv_data = clint_socket.recv(1024)#将bytes转化为字符串print('客户端数据:',recv_data.decode())#返回数据给客户端#读取文件file =open('./index.html','r',encoding='utf-8')send_data = file.read()# 构建响应报文#响应行response_line ='HTTP/1.1 200 ok \r\n'#响应头response_header = 'Server:python\r\n\r\n'#响应体response_body = send_data#拼接三部分数据构成完整的响应报文response_data = response_line + response_header + response_bodyclint_socket.send(response_data.encode())

你们细心点看的话 一定会发现 这几个的服务的代码都好像 没错啦 它们都是从最基本的服务器代码 变化过来的 只是为了实现不同的功能

多页面返回

import socketimport threading
# 1、创建服务端对象
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#绑定ip和端口
server.bind(('127.0.0.1',8008))#3、监听
server.listen(5)#循环等待客户端连接
while True:clinet_data,addr = server.accept()#接收客户端数据recv_data = clinet_data.recv(1024)print(recv_data)#读取请求报文中的请求路径,根据不同的请求路径返回不同的页面#1、将bytes类型转为字符串str_data = recv_data.decode()#2、字符串切割 按照\r\n进行切割 得到请求行 请求头请求体数据data_list = str_data.split('\r\n')print('切割后的列表数据',data_list)#3、从切割后的列表中提取请求行数据 在按照空格切割请求行数request_line = data_list[0]print('请求行数据',request_line)#4、空格切割请求路径url_path = request_line.split(' ')[1]print('切割数据',url_path)#5、根据不同的路径返回不同的页面if url_path == '/':file = open('./index.html','r',encoding='utf-8')send_data = file.read()file.close()elif url_path == '/request':#注册页面#读取注册页面的信息file1 = open('./request.html','r',encoding='utf-8')send_data = file1.read()file1.close()else:send_data = 'No found'#返回数据给客户端# file = open('./index.html','r',encoding='utf-8')# send_data = file.read()#构建报文数据#响应行response_line = 'http/1.1 200 ok \r\n'# 响应头response_header = 'Server:python\r\n\r\n'# 响应体response_body = send_data# 拼接三部分数据构成完整的响应报文response_data = response_line + response_header + response_bodyclinet_data.send(response_data.encode())

多任务静态页面

import socketimport threading#处理客户端请求
def clinet_info(clinet_data):# 接收客户端数据recv_data = clinet_data.recv(1024)print(recv_data)# 解决方案1 直接判断数据是否为空# if len(recv_data) == 0:# clinet_data.send('not data')#解决方案二 捕获数据异常 捕获到异常就结束函数的业务逻辑执行try:# 读取请求报文中的请求路径,根据不同的请求路径返回不同的页面# 1、将bytes类型转为字符串str_data = recv_data.decode()# 2、字符串切割 按照\r\n进行切割 得到请求行 请求头请求体数据data_list = str_data.split('\r\n')print('切割后的列表数据', data_list)# 3、从切割后的列表中提取请求行数据 在按照空格切割请求行数request_line = data_list[0]print('请求行数据', request_line)# 4、空格切割请求路径url_path = request_line.split(' ')[1]print('切割数据', url_path)except Exception as e:print(e)clinet_data.send('not data')return None# 5、根据不同的路径返回不同的页面if url_path == '/':file = open('./index.html', 'r', encoding='utf-8')send_data = file.read()file.close()elif url_path == '/request':# 注册页面# 读取注册页面的信息file1 = open('./request.html', 'r', encoding='utf-8')send_data = file1.read()file1.close()else:send_data = 'No found'# 返回数据给客户端# file = open('./index.html','r',encoding='utf-8')# send_data = file.read()# 构建报文数据# 响应行response_line = 'http/1.1 200 ok \r\n'# 响应头response_header = 'Server:python\r\n\r\n'# 响应体response_body = send_data# 拼接三部分数据构成完整的响应报文response_data = response_line + response_header + response_bodyclinet_data.send(response_data.encode())# 1、创建服务端对象
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#绑定ip和端口
server.bind(('127.0.0.1',8080))#3、监听
server.listen(5)
print('服务器就绪·······')#循环等待客户端连接
while True:clinet_data,addr = server.accept()#创建线程t = threading.Thread(target=clinet_info,args=(clinet_data,))t.start()server.close()

面向对象的静态服务器

import socket
import threading
class WebServer():def __init__(self):# 1、创建服务端对象self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 绑定ip和端口self.server.bind(('127.0.0.1', 8080))# 3、监听self.server.listen(5)def clinet_request(self,clinet_data):# 接收客户端数据recv_data = clinet_data.recv(1024)print(recv_data)# 解决方案1 直接判断数据是否为空# if len(recv_data) == 0:# clinet_data.send('not data')# 解决方案二 捕获数据异常 捕获到异常就结束函数的业务逻辑执行try:# 读取请求报文中的请求路径,根据不同的请求路径返回不同的页面# 1、将bytes类型转为字符串str_data = recv_data.decode()# 2、字符串切割 按照\r\n进行切割 得到请求行 请求头请求体数据data_list = str_data.split('\r\n')print('切割后的列表数据', data_list)# 3、从切割后的列表中提取请求行数据 在按照空格切割请求行数request_line = data_list[0]print('请求行数据', request_line)# 4、空格切割请求路径url_path = request_line.split(' ')[1]print('切割数据', url_path)except Exception as e:print(e)clinet_data.send('not data')return None# 5、根据不同的路径返回不同的页面if url_path == '/':file = open('./index.html', 'r', encoding='utf-8')send_data = file.read()file.close()elif url_path == '/request':# 注册页面# 读取注册页面的信息file1 = open('./request.html', 'r', encoding='utf-8')send_data = file1.read()file1.close()else:send_data = 'No found'# 返回数据给客户端# file = open('./index.html','r',encoding='utf-8')# send_data = file.read()# 构建报文数据# 响应行response_line = 'http/1.1 200 ok \r\n'# 响应头response_header = 'Server:python\r\n\r\n'# 响应体response_body = send_data# 拼接三部分数据构成完整的响应报文response_data = response_line + response_header + response_bodyclinet_data.send(response_data.encode())def start(self):print('服务器就绪·······')clinet_data, addr = self.server.accept()# 创建线程t = threading.Thread(target=self.clinet_request, args=(clinet_data,))t.start()

最后 演变出我们的mini_web服务器

import socket
import threading
import pymysql
import json
class WebServer():def __init__(self):# 1、创建服务端对象self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 绑定ip和端口self.server.bind(('127.0.0.1', 8000))# 3、监听self.server.listen(5)#路由列表self.url_list = [('/index',self.index),('/detail',self.detail)]def index(self,evn):db = pymysql.connect(user='数据库用户名', password='数据库密码', host='IP地址', database='所需使用的数据库')# 创建对象 (游标)cursor = db.cursor()# 编写sql语句sql_str = 'select * from bookinfo'cursor.execute(sql_str)# 获取所有的图书数据res_data = cursor.fetchall()data_list = []# 需要将所有图书数据转化为字典形式进行保存for book in res_data:# book数据还是元组 1是id 2是书名 3是作者 4是照片 5是分组data_list.append({
    'id': book[0],'name': book[1],'auth': book[2],'img_url': book[3],'rank': book[4]})# 再将字典数据转化为json返回send_data = json.dumps(data_list)return send_datadef detail(self,evn):query_data = evn['query_data']db = pymysql.connect(user='数据库用户名', password='数据库密码', host='IP地址', database='所需使用的数据库')# 创建对象 (游标)cursor = db.cursor()# 编写sql语句sql_str = 'select * from bookinfo where ' + query_datacursor.execute(sql_str)# 获取图书数据book = cursor.fetchone()# 将获取的元组数据转化为字典data_dict = {
    'id': book[0],'name': book[1],'auth': book[2],'img_url': book[3],'rank': book[4]}# 将字典数据转化为jsonsend_data = json.dumps(data_dict)return send_datadef url_route(self,evn):#封装处理路径判断的业务逻辑url_path = evn['url_path']# if url_path == '/':# #查询所有数据再返回# send_data= self.index(evn)## elif url_path == '/detail':# #获取图书详情数据# send_data = self.detail(evn)# else:# send_data = 'No found'for url,func in self.url_list:if url == url_path:send_data = func(evn)breakelse:send_data = ''return send_datadef clinet_request(self,clinet_data):# 接收客户端数据recv_data = clinet_data.recv(1024)print(recv_data)# 解决方案1 直接判断数据是否为空# if len(recv_data) == 0:# clinet_data.send('not data')# 解决方案二 捕获数据异常 捕获到异常就结束函数的业务逻辑执行try:# 读取请求报文中的请求路径,根据不同的请求路径返回不同的页面# 1、将bytes类型转为字符串str_data = recv_data.decode()# 2、字符串切割 按照\r\n进行切割 得到请求行 请求头请求体数据data_list = str_data.split('\r\n')print('切割后的列表数据', data_list)# 3、从切割后的列表中提取请求行数据 在按照空格切割请求行数request_line = data_list[0]print('请求行数据', request_line)# 4、空格切割请求路径url_path = request_line.split(' ')[1]print('切割数据', url_path)except Exception as e:print(e)clinet_data.send(b'not data')return Noneprint(url_path)#判断路径是否有问号携带的数据url_data = url_path.split('?')if len(url_data) > 1:#说明路径中有问号#重新给路径赋值url_path = url_data[0]#获取问号后的查询数据query_data = url_data[1]else:#没有问号?数据query_data = ''# 5、根据不同的路径返回不同的页面evn = {
    'url_path':url_path,'query_data':query_data}#接收查询后的数据send_data = self.url_route(evn)# 返回数据给客户端# file = open('./index.html','r',encoding='utf-8')# send_data = file.read()# 构建报文数据# 响应行response_line = 'http/1.1 200 ok \r\n'# 响应头response_header = 'Server:python\r\n\r\n'# 响应体response_body = send_data# 拼接三部分数据构成完整的响应报文response_data = response_line + response_header + response_bodyclinet_data.send(response_data.encode('utf8'))def start(self):print('服务器就绪·······')while True:clinet_data, addr = self.server.accept()# 创建线程t = threading.Thread(target=self.clinet_request, args=(clinet_data,))t.start()web = WebServer()
web.start()

这里面的代码 我来来回回的也改了好多 有些杂乱 最近很忙没什么时间 有什么问题 欢迎到评论区留言

拜拜

  相关解决方案