博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
写一个简单的webserver
阅读量:7050 次
发布时间:2019-06-28

本文共 2871 字,大约阅读时间需要 9 分钟。

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

WEB服务器原理

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

socket连接

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

import socketsk = socket.socket(    socket.AF_INET,     socket.SOCK_STREAM)# 监听本地 8888 端口host = '127.0.0.1'port = 8888sk.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.1Host: xxxConnection: xxxCache-Control: xxxUpgrade-Insecure-Requests: xxxUser-Agent: xxxAccept: xxxAccept-Encoding: xxxAccept-Language: xxxCookie: 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 += chunkexcept:    pass

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

try:    f = open(path, 'r')    while True:        chunk = f.read(1024)        if not chunk:            f.close()            break;        content += chunkexcept:    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'# 组合成响应报文 resres = headers + contentType + contentLen + '\r\n' + content# 编码后发送给浏览器,# 至此,本次通信结束clientSk.sendall(res.encode(encoding='UTF-8'))clientSk.close()

示例

到项目GitHub:,下载本项目到本地,双击 server.py,并访问 ,你应该会看到十分亲切的 Hello world!

转载地址:http://ubcol.baihongyu.com/

你可能感兴趣的文章
js中call与apply
查看>>
隐式转换
查看>>
(转)直接拿来用!最火的iOS开源项目(二)
查看>>
mybatis 实体嵌套查询
查看>>
跨境物流链路怎么做?菜鸟工程师打造了全球通关“神器”
查看>>
mysql数据库的修改
查看>>
Ubuntu Server 16升級到Ubuntu Server 18操作步驟
查看>>
Android中ViewGroup
查看>>
世界上最受欢迎的10个Linux发行版
查看>>
Ubuntu 14.04数据库服务器--mysql的安装,配置,卸载
查看>>
网站后端_Python+Flask.0005.FLASK调试模式之开启DEBUG与PIN使用?
查看>>
用pushd、popd和cd - 快速定位目录
查看>>
Android安全防护之旅---带你把Apk混淆成中文语言代码
查看>>
mysql清空表的方法
查看>>
Http协议及apache配置笔记
查看>>
读书笔记-大颠狂(非同寻常的大众幻想与群众性癫狂)
查看>>
MySQL 多条数据的一个字段合并
查看>>
jquery AJAX清除IE缓存问题
查看>>
Percona XtraBackup (译一):首页
查看>>
一大早就解决了个服务器***问题
查看>>