我的编程空间,编程开发者的网络收藏夹
学习永远不晚

写一个简单的webserver

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

写一个简单的webserver

基于 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()

示例

到项目GitHub:https://github.com/hanrenguang/simple-webserver,下载本项目到本地,双击 server.py,并访问 http://localhost:8888/index.html,你应该会看到十分亲切的 Hello world!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

写一个简单的webserver

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

写一个简单的webserver

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

一个简单的WebServer,socke

import socketimport threadingbody = '

web server

'response_params = [ 'HTTP/1.0 200 OK', 'Content-Type: t
2023-01-31

HTML怎么编写一个简单的表单

这篇文章主要介绍了HTML怎么编写一个简单的表单,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。我们先来看下常用的表单元素有哪些: 文本域 文本域通过
2023-06-27

用Python编写一个简单的Http S

原文地址:Write a simple HTTP server in Python http://www.acmesystems.it/python_httpd 例子中源码: https://github.com/tanzilli/play
2023-01-31

用Python写一个简单公众号

前言:虽然简单,但是稍稍还是有点可取的地方的,终于可以有一个可以作为项目放在自己的github上了T_T,一个好项目一定是可拔插好扩展的,离好项目至少60%吧,以后再进一步完善了。   说实话,有一个微信公众号还是蛮方便的,可以将一些自己常
2023-01-31

Python编写一个简单计算器

一个计算器最主要的功能是加减乘除,那么用 Python 可以怎样实现呢#!/usr/bin/env python# -*- coding:utf-8 -*-# @Time : 2018/1/22 22:29# @Author : z
2023-01-31

教你使用Python写一个简单的JSONParser

这篇文章主要介绍了教你使用Python写一个简单的JSONParser,它的整个效果,有点类似于python标准库json的json.load()方法,需要的朋友可以参考下
2023-05-14

python写一个简单的俄罗斯方块

# teris.py# A module for game teris.# By programmer FYJfrom tkinter import *from time import sleepfrom random import *fr
2023-01-31

如何用python写一个简单的find命

对一个运维来说可能会经常去查找目录下的一些文件是否存在,最常用的就是find命令,它不仅可以查找文件也可以查找目录,find命令用法查找文件[root@node1 opt]# find /usr/ -type f -name df/usr/
2023-01-31

如何编写一个VBScript简单的页面

这篇文章主要介绍“如何编写一个VBScript简单的页面”,在日常操作中,相信很多人在如何编写一个VBScript简单的页面问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何编写一个VBScript简单的页面
2023-06-09

如何使用Python写一个简单的JSONParser

本篇内容主要讲解“如何使用Python写一个简单的JSONParser”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何使用Python写一个简单的JSONParser”吧!JSON Token
2023-07-06

Python写一个简单的api接口的实现

本文主要介绍了Python写一个简单的api接口的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2023-02-14

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录