Python使用socket实现简易的http服务
在接触的一些项目中,有时为了方便可视化一些服务状态(请求数很少),那么很容易想到使用http服务来实现。但开源的web后端框架,例如flask,fastapi,django等略显沉重,且使用这些框架会有各种各样的限制,为了更加灵活的使用,可以自己通过Python自带的socket库来实现,下面是我简单实现的代码,贴在这里方便后续使用。
客户端代码:
import os
import time
import json
import socket
import datetime
import traceback
from urllib import parse
from concurrent.futures import ThreadPoolExecutorENCODING = "utf-8"class CustomRouter:def __init__(self):self.router_dict = {}def register(self, url: str, method: str):if method not in ["GET", "POST"]:raise ValueError(f"method only support GET or POST, got {method}")key = f"{url}:{method}"if key in self.router_dict:raise ValueError(f"url:{url} method:{method} already registed")def _register(func):self.router_dict[key] = funcreturn funcreturn _registerdef has_register(self, url: str, method: str):key = f"{url}:{method}"return key in self.router_dictdef request(self, url: str, method: str):key = f"{url}:{method}"func = self.router_dict[key]return func()router = CustomRouter()@router.register(url="/", method="GET")
def task():return "Hello World!!!"@router.register(url="/get_project_info", method="GET")
def get_project_info():info = {"pwd": os.path.abspath(os.curdir),"encoding": ENCODING,"time": datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}return json.dumps(info)class CustomServer:def __init__(self, port: int = 5055, backlog: int = 2, num_workers: int = 2):self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)self.server.bind(("", port))self.server.listen(backlog)self.buff_size = 1024self.encoding = ENCODINGself.router = routerself.timeout = 60self.thread_pool = ThreadPoolExecutor(max_workers=num_workers)def parse_message(self, message: str):method, url_params, message = message.split(" ", maxsplit=2)res = parse.urlparse(url_params)url = res.pathparams = dict([i for i in parse.parse_qsl(res.query)])version, message = message.split("\r\n", maxsplit=1)return method, url, params, versiondef task(self, conn: socket.socket, addr):conn.settimeout(self.timeout)try:message = conn.recv(self.buff_size).decode(self.encoding)t0 = time.perf_counter()method, url, params, version = self.parse_message(message)if not self.router.has_register(url, method):conn.send("HTTP/1.1 501 Not Implemented\r\n\r\n".encode(self.encoding))print(f"[{method}][501]client addr: {addr} request: {url}, time: {time.perf_counter() - t0:.5f}")conn.close()returnres = self.router.request(url, method)conn.send("HTTP/1.1 200 OK\r\n\r\n".encode(self.encoding))conn.send(res.encode(self.encoding))print(f"[{method}][200]client addr: {addr} request: {url}, time: {time.perf_counter() - t0:.5f}")except (BrokenPipeError, TimeoutError):print(traceback.format_exc())except:print(traceback.format_exc())conn.send("HTTP/1.1 500 Inner Error\r\n\r\n".encode(self.encoding))print(f"[{method}][500]client addr: {addr} request: {url}, time: {time.perf_counter() - t0:.5f}")finally:conn.close()def run(self):while True:conn, addr = self.server.accept()self.thread_pool.submit(self.task, conn, addr)if __name__ == '__main__':s = CustomServer()s.run()
客户端代码:
import requestsdef main():for _ in range(50):res = requests.get("http://127.0.0.1:5055")print(res.status_code, res.text)res = requests.get("http://127.0.0.1:5055/get_project_info")print(res.status_code, res.json())if __name__ == '__main__':main()
客户端请求时,服务端终端输出:
[GET][200]client addr: ('127.0.0.1', 38054) request: /, time: 0.00002
[GET][200]client addr: ('127.0.0.1', 38058) request: /get_project_info, time: 0.00004
[GET][200]client addr: ('127.0.0.1', 38060) request: /, time: 0.00002
[GET][200]client addr: ('127.0.0.1', 38070) request: /get_project_info, time: 0.00004
[GET][200]client addr: ('127.0.0.1', 38080) request: /, time: 0.00002
[GET][200]client addr: ('127.0.0.1', 38096) request: /get_project_info, time: 0.00004
[GET][200]client addr: ('127.0.0.1', 38098) request: /, time: 0.00002
[GET][200]client addr: ('127.0.0.1', 38114) request: /get_project_info, time: 0.00009
[GET][200]client addr: ('127.0.0.1', 38120) request: /, time: 0.00003
[GET][200]client addr: ('127.0.0.1', 38122) request: /get_project_info, time: 0.00006
[GET][200]client addr: ('127.0.0.1', 38136) request: /, time: 0.00003
[GET][200]client addr: ('127.0.0.1', 38146) request: /get_project_info, time: 0.00006
[GET][200]client addr: ('127.0.0.1', 38160) request: /, time: 0.00003
[GET][200]client addr: ('127.0.0.1', 38172) request: /get_project_info, time: 0.00005
[GET][200]client addr: ('127.0.0.1', 38178) request: /, time: 0.00002
[GET][200]client addr: ('127.0.0.1', 38182) request: /get_project_info, time: 0.00005
客户端终端输出:
200 Hello World!!!
200 {'pwd': '/home/wz/my_projects/others/socket_t', 'encoding': 'utf-8', 'time': '2025-01-14 00:20:01'}
200 Hello World!!!
200 {'pwd': '/home/wz/my_projects/others/socket_t', 'encoding': 'utf-8', 'time': '2025-01-14 00:20:01'}
200 Hello World!!!
200 {'pwd': '/home/wz/my_projects/others/socket_t', 'encoding': 'utf-8', 'time': '2025-01-14 00:20:01'}
200 Hello World!!!
200 {'pwd': '/home/wz/my_projects/others/socket_t', 'encoding': 'utf-8', 'time': '2025-01-14 00:20:01'}
200 Hello World!!!
200 {'pwd': '/home/wz/my_projects/others/socket_t', 'encoding': 'utf-8', 'time': '2025-01-14 00:20:01'}
200 Hello World!!!
200 {'pwd': '/home/wz/my_projects/others/socket_t', 'encoding': 'utf-8', 'time': '2025-01-14 00:20:01'}
200 Hello World!!!
200 {'pwd': '/home/wz/my_projects/others/socket_t', 'encoding': 'utf-8', 'time': '2025-01-14 00:20:01'}
200 Hello World!!!
200 {'pwd': '/home/wz/my_projects/others/socket_t', 'encoding': 'utf-8', 'time': '2025-01-14 00:20:01'}
相关文章:
Python使用socket实现简易的http服务
在接触的一些项目中,有时为了方便可视化一些服务状态(请求数很少),那么很容易想到使用http服务来实现。但开源的web后端框架,例如flask,fastapi,django等略显沉重,且使用这些框架会有…...
【Hive】海量数据存储利器之Hive库原理初探
文章目录 一、背景二、数据仓库2.1 数据仓库概念2.2 数据仓库分层架构2.2.1 数仓分层思想和标准2.2.2 阿里巴巴数仓3层架构2.2.3 ETL和ELT2.2.4 为什么要分层 2.3 数据仓库特征2.3.1 面向主题性2.3.2 集成性2.3.3 非易失性2.3.4 时变性 三、hive库3.1 hive概述3.2 hive架构3.2.…...
linux系统监视(centos 7)
一.系统监视 1.安装iostat,sar,sysstat(默认没有,安装过可以跳跃) iostat 和 sar: 同样,iostat 和 sar 是 sysstat 软件包的一部分。使用以下命令安装:sudo yum install sysstat解释…...
Blazor中Syncfusion图像编辑器组件使用方法
Blazor中Syncfusion图像编辑器组件是一个功能丰富的图像处理工具,支持多种编辑、操作和交互方式,帮助用户高效处理图像。以下是该组件的主要功能总结: 主要功能: 图像打开与保存 图像编辑器允许用户通过简单的点击操作打开支持的…...
电动汽车V2G技术Matlab/Simulink仿真模型
今天给大家更新关于V2G技术的仿真,不是研究这个方向的,可能会对这个名称比较陌生,那么,什么是“V2G”? V2G全称:Vehicle-to-Grid,即车网互动,利用电动汽车特有的储能功能与电网“双…...
C++中的unordered_set和unordered_map的模拟实现
一、封装基本结构 与map和set的封装过程很想,unordered_set和unordered_map也需要用MapKeyOfT和SetKeyOfT创建哈希表类型,借此获取对应的key值来使用; 因此,在哈希表中也一样需要用参数class T来替代set中的key和map中的pair<…...
Spring Boot 2 学习指南与资料分享
Spring Boot 2 学习资料 Spring Boot 2 学习资料 Spring Boot 2 学习资料 在当今竞争激烈的 Java 后端开发领域,Spring Boot 2 凭借其卓越的特性,为开发者们开辟了一条高效、便捷的开发之路。如果你渴望深入学习 Spring Boot 2,以下这份精心…...
(一)QSQLite3库简介
1、SQLite数据库 SQLite数据库,作为一个轻量级的关系型数据库管理系统,广泛应用于移动设备和桌面应用程序中。由于其简单易用、无需配置的特点,它为开发者提供了极大的便利。然而,正是由于其应用广泛,随着用户对于系统…...
《计算机网络》课后探研题书面报告_网际校验和算法
网际校验和算法 摘 要 本文旨在研究和实现网际校验和(Internet Checksum)算法。通过阅读《RFC 1071》文档理解该算法的工作原理,并使用编程语言实现网际校验和的计算过程。本项目将对不同类型的网络报文(包括ICMP、TCP、UDP等&a…...
hot100_240. 搜索二维矩阵 II
hot100_240. 搜索二维矩阵 II 直接遍历列减行增 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性: 每行的元素从左到右升序排列。 每列的元素从上到下升序排列。 示例 1: 输入:matrix [[1,4,7,1…...
78_Redis网络模型
1.Redis网络模型概述 1.1 Redis网络模型介绍 Redis 7.x的网络模型基于epoll的Reactor模式实现,这是一个高效的事件驱动模型。在Redis中,所有的网络事件(如连接、读写等)都由一个事件循环(Event Loop)来处理。这个事件循环负责监听套接字上的事件,并根据事件类型调用相…...
python范围
用户图形界面-工资计算器 from tkinter import *def f():w int(e1.get()) int(e2.get()) - int(e3.get())wage.insert(0,w)root Tk() root.title("工资计算器") Label(root, text"每月基本工资:").pack() e1 Entry(root) e1.pack() Label(…...
vulnhub靶场【Raven系列】之2 ,对于mysql udf提权的复习
前言 靶机:Raven-2,IP地址为192.168.10.9 攻击:kali,IP地址为192.168.10.2 都采用虚拟机,网卡为桥接模式 文章所用靶机来自vulnhub,可通过官网下载,或者通过链接:https://pan.quark.cn/s/a65…...
基于vite+vue3+mapbox-gl从零搭建一个项目
下面是基于 Vite、Vue 3 和 Mapbox GL 从零搭建一个项目的完整步骤,包括环境搭建、依赖安装、配置和代码示例。 1. 初始化项目 首先,使用 Vite 快速创建一个 Vue 3 项目: npm create vuelatest vue3-mapboxgl --template vue cd vue3-mapbo…...
向harbor中上传镜像(向harbor上传image)
向 Harbor 中上传镜像通常分为以下几个步骤: 1、登录 Harbor 2、构建镜像 3、标记镜像 4、推送镜像到 Harbor 仓库 1、登录 Harbor 首先,确保你已经能够访问 Harbor,并且已经注册了账户。如果还没有 Harbor 账户,你需要先注册一…...
【线性代数】行列式的性质
行列式性质定理讲义 一、行列式的基本性质 性质 1:行列互换 对于任意一个 n n n \times n nn 的方阵 A A A,其行列式 ∣ A ∣ |A| ∣A∣ 满足: ∣ A ∣ ∣ A T ∣ |A| |A^T| ∣A∣∣AT∣ 其中, A T A^T AT 是 A A A 的…...
智能家居企业如何通过设计师渠道打造第二曲线?
随着智能家居行业的迅速发展和消费者需求的不断升级,企业的营销策略也在不断变化。传统的B2C营销模式逐渐让位于更加精细化、定制化的B2B2C模式,其中设计师渠道的开发与合作,成为智能家居企业布局市场、提升品牌影响力的关键。 智能家居推广的…...
Unity3d 实时天气系统基于UniStorm插件和xx天气API实现(含源码)
前言 实时天气在Unity3d三维数字沙盘中的作用非常重要,它能够增强虚拟环境的真实感和互动性,实时天气数据的应用可以提供更为精准和直观的天气信息支持,如果真实的数据加上特效、声音和模型反馈会提高产品档次,提高真实感。 目前…...
年后找工作需要注意的事项
大家好!我是 [数擎 AI],一位热爱探索新技术的前端开发者,在这里分享前端和 Web3D、AI 技术的干货与实战经验。如果你对技术有热情,欢迎关注我的文章,我们一起成长、进步! 开发领域:前端开发 | A…...
模拟器多开窗口单IP与代理IP关系
模拟器多开窗口同IP背后出现的问题 在游戏世界中,模拟器多开窗口是玩家们提升体验的常见做法。通过在同一设备上开启多个模拟器窗口,玩家可以同时运营多个游戏账号,增加游戏的趣味性和效率。 一旦检测到一个IP地址下登录了过多的账号&#x…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...
