基于 Python3 写的极简版 webserver。用于学习 HTTP协议,及 WEB服务器 工作原理。笔者对 WEB服务器 的工作原理理解的比较粗浅,仅是基于个人的理解来写的,存在很多不足和漏洞,目的在于给大家提供一个写 webserver 的思路。项目GitHub地址:https://github.com/hanrenguang/simple-webserver。

WEB服务器原理

学过计网的同学应该都知道 HTTP协议 是在 TCP协议 之上实现的。浏览器与服务器之间的通信首先是建立 TCP 连接,再进行请求和响应报文的传输。服务器是属于被动的一方,当浏览器发起请求的时候,服务器才能和浏览器通信,在此之前,服务器都处于一个等待监听的状态。

socket连接

实现服务器的第一步是建立一个 socket 连接,socket 套接字是对 TCP/UDP协议 的一个封装,Python 就自带有 socket 模块,所以使用起来很方便。

import socket

sk = socket.socket(

socket.AF_INET,

socket.SOCK_STREAM

)

# 监听本地 8888 端口

host = '127.0.0.1'

port = 8888

sk.bind((host, port))

sk.listen(5)

while True:

try:

clientSk, addr = sk.accept()

print("address is: %s" % str(addr))

req = clientSk.recv(1024)

clientSk.sendall('...')

clientSk.close()

except Exception as err:

print(err)

clientSk.close()

这是一个极简的 socket-server,需要注意的是,我们仅实现了 TCP协议 的部分。

解析HTTP请求

拿到浏览器的请求很简单,clientSk.recv() 即可获取请求报文,而些数据我们无法直接拿来用,因为它是基于 HTTP协议 封装的数据,在我们进行下一步操作前,需要对请求报文“解封”。而在此之前,我们需要了解请求报文的格式。最快捷的方式呢,是打开浏览器(以 chrome 为例),随便打开百度啥的,F12 打开开发者工具,在 Network 一栏就可以观察到。大概长下面这样:

GET / HTTP/1.1

Host: xxx

Connection: xxx

Cache-Control: xxx

Upgrade-Insecure-Requests: xxx

User-Agent: xxx

Accept: xxx

Accept-Encoding: xxx

Accept-Language: xxx

Cookie: xxx

我们把关注点放在第一行,GET 方法,请求的资源路径为 /,使用的协议是 HTTP1.1,之后就是一回车换行符 \r\n。所以我们对报文的解析如下(存在许多不足之处):

# 第一步先对数据进行解码 decode(),

# 再以行为单位进行分割

requestList = clientSk.recv(1024).decode().split("\r\n")

# 调用写好的函数对其进行解析

parseReq(requestList)

# 解析请求报文

def parseReq(reqList):

# 保存解析结果

parseRet = {}

# 请求的方法,如 GET

method = reqList[0].split(' ')[0]

# 请求的资源路径,如 '/'

sourcePath = reqList[0].split(' ')[1]

parseRet['method'] = method

parseRet['sourcePath'] = sourcePath

i = len(reqList) - 1

# 以 key: value 的形式保存解析结果

while i:

if len(reqList[i].split(':')) == 1:

i = i - 1

continue

idx = reqList[i].find(':')

key, value = reqList[i][0:idx], reqList[i][idx+1:]

parseRet[key] = value.strip()

i = i - 1

return parseRet

构造响应报文

拿到了请求报文并将其解析后,我们可以开始构造响应报文的内容了,以请求静态资源为例,假设请求报文第一行为 GET /index.html HTTP/1.1。那么我首先要做的就是先获取路径为 /index.html 的文件内容:

# 获取资源内容

try:

f = open(path, 'r')

while True:

chunk = f.read(1024)

if not chunk:

f.close()

break;

content += chunk

except:

pass

那接下来就是构造响应报文了,同理可以观察 HTTP 响应报文的格式,在此就不举例了,直接上代码:

try:

f = open(path, 'r')

while True:

chunk = f.read(1024)

if not chunk:

f.close()

break;

content += chunk

except:

pass

# 省略了大部分头部信息

headers = 'HTTP/1.1 200 OK\r\n'

contentType = 'Content-Type: text/html; charset=utf-8\r\n'

contentLen = 'Content-Length: ' + str(len(content)) + '\r\n'

# 组合成响应报文 res

res = headers + contentType + contentLen + '\r\n' + content

# 编码后发送给浏览器,

# 至此,本次通信结束

clientSk.sendall(res.encode(encoding='UTF-8'))

clientSk.close()

示例

python3web库_基于 Python3 写的极简版 webserver相关推荐

  1. python获取app信息的库_基于python3抓取pinpoint应用信息入库

    这篇文章主要介绍了基于python3抓取pinpoint应用信息入库,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Pinpoint是用Java编写 ...

  2. 自己写一个极简浏览器

    自己写一个极简浏览器 --基于Chromium的浏览器 我的Github地址: 官方:https://github.com/KaiHuaDou/EasyBrowserAdvanced/releases ...

  3. Serverless 实战 —— 基于 Serverless 的 VuePress 极简静态网站

    基于 Serverless 的 VuePress 极简静态网站 作者: Aceyclee 之前用过 Docsify + Serverless Framework 快速创建个人博客系统,虽然 docsi ...

  4. 7句话让Codex给我做了个小游戏,还是极简版塞尔达,一玩简直停不下来

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 梦晨 萧箫 发自 凹非寺 量子位 | 公众号 QbitAI 什么,7 ...

  5. Underscore源码阅读极简版入门

    看了网上的一些资料,发现大家都写得太复杂,让新手难以入门.于是写了这个极简版的Underscore源码阅读. 源码: github.com/hanzichi/un- 一.架构的实现 1.1:架构 (f ...

  6. Atlas 200 DK开发者套件环境部署(1.0.9.alpha)极简版

    Atlas 200 DK开发者套件环境部署(1.0.9.alpha)极简版 前言 Atlas 200 DK开发者套件介绍 环境部署介绍 资源要求 开发环境部署 安装Docker 获取镜像(两种方法任选 ...

  7. python入门笔记——飞机大战(极简版、未进行继承优化)

    python入门笔记--飞机大战(极简版.未进行继承优化) import random import pygame# 引用pygame里的模块 from pygame.locals import *# ...

  8. 【Liunx】进程的程序替换——自定义编写极简版shell

    目录 进程程序替换[1~5] 1.程序替换的接口(加载器) 2.什么是程序替换? 3.进程替换的原理 4.引入多进程 5.系列程序替换接口的详细解析(重点!) 自定义编写一个极简版shell[6~8] ...

  9. 很多小伙伴不太了解ORM框架的底层原理,这不,冰河带你10分钟手撸一个极简版ORM框架(赶快收藏吧)

    大家好,我是冰河~~ 最近很多小伙伴对ORM框架的实现很感兴趣,不少读者在冰河的微信上问:冰河,你知道ORM框架是如何实现的吗?比如像MyBatis和Hibernate这种ORM框架,它们是如何实现的 ...

最新文章

  1. +[NSTimer scheduledTimerWithTimeInterval:repeats:block:]: unrecognized selector sent to xxx
  2. Host 'controller' is not mapped to any cell
  3. 一个有趣的问题,讨论讨论
  4. Java8新特性--CompletableFuture
  5. uva 294 ——Divisors
  6. android 获取系统时间的时间戳 ,时间戳日期互转,计算日期时间差,获取明天日期,比较时间大小
  7. mysql冷热数据LRU_浅析MySQL的lru链表
  8. git 可视化工具_Git的基本使用(二)
  9. AI项目商务合作,寻广州附近计算机视觉算法团队!
  10. Redis集成到Maven工程(Jedis客户端)
  11. mysql锁表语句,从理论到实践!
  12. Android Material Design调色板
  13. [codeblocks下实现多个源文件2.0]类声明和成员函数定义的分离实战操作实现
  14. 录音软件行业调研报告 - 市场现状分析与发展前景预测
  15. 类和对象6:相关内置函数
  16. ODT(old driver tree)详解(带例题)
  17. 三十八、西梁女儿国疑案之一落胎泉的秘密
  18. 通达信 c java,通达信的c
  19. win10系统安装到服务器失败怎么解决,windows10安装失败怎么办?解决win10安装失败的方法教程[多图]...
  20. 大数据夯实基础_2019_1_7

热门文章

  1. java.sql.SQLException: Access denied for user 'Administrator'@'localhost' (using password: YES)
  2. -------------计算机里面算法-----------
  3. 如何获取select中的value、text、index相关值 如何获取单选框中radio值 触发事件 radio 默认选中...
  4. 通过bin-log对mysql进行数据恢复
  5. 李炎恢的课程中心(JQUERY视频)
  6. 1.5 推荐优秀书籍 - 网站重构与Web标准设计 - 学习笔记
  7. [转]java中的值传递和引用传递
  8. python 决策树回归参数_python决策树之CART分类回归树详解
  9. pads中如何设置等长_如何在Windows 10中设置和使用Hyper-V进行OS虚拟化
  10. Ubuntu20.04之安装VirtualBox虚拟机