Web静态服务器

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: Web静态服务器

1前情回顾

域名后面没有加端口,就是采用默认的端口。HTTP是80HTTPS是443

请求报文格式:请求行,请求头,空行,请求体。前三个每个后面都有\r\n

响应报文格式:响应行、响应头、空行、响应体。

状态码:2xx成功3xx重定向4xx客户端错误5xx服务器错误

HTTP协议用在浏览器和服务器之间

应用层协议

基于TCP

工作模式:一次请求,一次响应。多次请求,多次响应

提前将每个知识点过一遍

2 web服务器

2.1目的

理解一下web服务器的出路流程

将前面的知识融合起来

2.2介绍

简单扩充一下:

互联网:泛指一切可以互联互通的网络

因特网:偏向于网页、邮件之类的(不包括局域网)外网

万维网:特指浏览器和web服务器之间的

2.3 案例

2.3.1返回固定数据

注意:三引号是一个多行字符串,有注释的功能

1"""
 2三引号是一个多行字符串,有注释的功能
 3"""
 4import socket
 5def main():
 6   # 1创建套接字  绑定 监听套接字
 7   server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 8   server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
 9   server_socket.bind(('',10086))
10   server_socket.listen(128)
11   while True:
12       # 2 不断接受连接
13       client_socket,client_addr = server_socket.accept()
14       print("接受到了来自%s的连接请求" % str(client_addr))
15       # 3 接收请求报文
16       request_data = client_socket.recv(4096).decode()
17       # 4 解析请求报文  得到用户的资源路径
18       # 5 读取对应资源 封装在http响应报文中发送给浏览器
19       response_line = 'HTTP/1.1 200 OK\r\n'   # 响应行 状态行
20       # 如果想要显示中文 网页默认是gbk
21       # 加入'Content-Type: text/html;charset=UTF-8\r\n'
22       response_header = 'Server: BMW1.0\r\n'   # 响应头
23       request_body = 'Hello Ethan yan'   # 响应体
24       response_data = response_line + response_header +'\r\n'+request_body
25       client_socket.send(response_data.encode())
26       # 6 在合适的位置关闭套接字
27       client_socket.close()
28
29if __name__ == '__main__':
30   main()

2.3.2返回固定网页

1import socket
 2def main():
 3   server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 4   server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
 5   server_socket.bind(('',10010))
 6   server_socket.listen(128)
 7   while True:
 8       client_socket,client_addr = server_socket.accept()
 9       print("来自%s的最强王者上线了...." % str(client_addr))
10       request_data = client_socket.recv(4096).decode()
11       print("请求报文".center(30,'='))
12       print(request_data)
13       response_line = 'HTTP/1.1 200 OK\r\n'
14       response_header = 'Server: BMW1.0\r\n'+ 'Content-Type: text/html;charset=UTF-8\r\n'
15       # response_body = "来啦?老弟"
16       with open('index.html','rb') as file:
17           response_body = file.read()
18       response_data = (response_line + response_header + '\r\n').encode() + response_body
19       client_socket.send(response_data)
20       client_socket.close()
21
22if __name__ == '__main__':
23   main()


2.3.3返回指定网页

1import socket
 2import re
 3def main():
 4   server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 5   server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
 6   server_socket.bind(('',10010))
 7   server_socket.listen(128)
 8   while True:
 9       client_socket,client_addr = server_socket.accept()
10       print("来自%s的最强王者上线了...." % str(client_addr))
11       request_data = client_socket.recv(4096).decode()
12       if not request_data:
13           print("最强王者已经下限了")
14           client_socket.close()
15           continue
16
17       # GET /index2.html HTTP/1.1\r\n
18       # 切割请求报文 第0个元素就是请求行
19       # 连接的时候,浏览器会提前创建好几个链接
20       request_line = request_data.split('\r\n')[0]
21       # 从请求行中提取出用户的资源请求路径
22       result = re.match(r'\w+\s+(\S+)',request_line)
23       if not result:
24           print("用户请求错误")
25           client_socket.close()
26           continue
27       print("用户的请求路径是%s" % result.group(1))
28       path_info = result.group(1)
29       # 当用户请求/  表示首页  返回一个首页资源
30       if path_info == '/':
31           path_info = '/index.html'
32
33       response_line = 'HTTP/1.1 200 OK\r\n'
34       response_header = 'Server: BMW1.0\r\n'
35       # response_body = "来啦?老弟"
36       # 加'static'表示用户请求的路径都在这个路径下,从而保证系统的安全
37
38       with open('static'+path_info,'rb') as file:
39           response_body = file.read()
40       response_data = (response_line + response_header + '\r\n').encode() + response_body
41       client_socket.send(response_data)
42       client_socket.close()
43
44if __name__ == '__main__':
45   main()

2.3.4增加404页面

1import socket
 2import re
 3import os
 4"""
 5web服务作用:  接收请求报文 返回网页资源给web浏览器
 6
 7web服务器流程:
 8   1 创建 绑定 监听套接字
 9   2 接受连接
10   3 接收请求报文
11   4 解析请求报文 得到用户的资源请求路径
12   5 读取对应资源 封装在HTTP响应报文中发送给浏览器
13   6 在合适的位置关闭套接字即可
14"""
15def main():
16   # 1 创建 绑定 监听套接字
17   server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
18   server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
19   server_socket.bind(('', 9999))
20   server_socket.listen(128)
21
22   # 2 不断地接受连接
23   while True:
24       client_socket, client_addr = server_socket.accept()
25       print("接受到了来自%s的连接请求" % str(client_addr))
26
27       # 3 接收请求报文
28       request_data = client_socket.recv(4096).decode()
29       if not request_data:
30           print("用户已经断开连接了")
31           client_socket.close()
32           continue
33
34       # 4 解析请求报文 得到用户的资源请求路径  "GET /index2.html HTTP/1.1\r\n..."
35       # 4.1 切割请求报文 第0个元素就是请求行
36       request_line = request_data.split("\r\n")[0]
37       # 4.2 从请求行中提取出 用户资源请求路径
38       result = re.match(r"\w+\s+(\S+)", request_line)
39       if not result:
40           print("用户请求格式错误")
41           client_socket.close()
42           continue
43
44       print("用户请求的路径是%s" % result.group(1))  # /home/python/Desktop/index.html
45       path_info = result.group(1)
46       # 当用户请求/ 表示首页  返回一个首页资源
47       if path_info == '/':
48           path_info = '/index.html'
49       response_header = "Server: PWS1.0\r\n"  # 响应头
50       # 5 读取对应资源 封装在HTTP响应报文中发送给浏览器
51       if not os.path.exists("static" + path_info):
52           response_line = "HTTP/1.1 404 Not Found\r\n"
53           with open("static/404.html","rb") as file:
54               response_body = file.read()
55       else:
56           response_line = "HTTP/1.1 200 OK\r\n"  # 响应行 状态行
57
58           with open("static" + path_info, "rb") as file:
59               response_body = file.read()
60
61       response_data = (response_line + response_header + "\r\n").encode() + response_body
62       client_socket.send(response_data)
63
64       # 6 在合适的位置关闭套接字即可
65       client_socket.close()

文本文件二进制编码解码没有问题,但是如果是图片,就会出现问题

协程用在web

如果在发送文件的时候,有可能一次发送不完整,显示有误,可能是文件太大。我们可以将send方法改成sendall方法,即可解决

2.3.5 多任务

1from gevent import monkey
 2monkey.patch_all()   # 自动切换  recv accept time.sleep
 3import socket
 4import re
 5import os
 6import gevent
 7
 8"""
 9web服务作用:  接收请求报文 返回网页资源给web浏览器
10
11web服务器流程:
12   1 创建 绑定 监听套接字
13   2 接受连接
14   3 接收请求报文
15   4 解析请求报文 得到用户的资源请求路径
16   5 读取对应资源 封装在HTTP响应报文中发送给浏览器
17   6 在合适的位置关闭套接字即可
18"""
19def request_handler(client_socket):
20   """这个函数用来处理客户端请求的"""
21   # 3 接收请求报文
22   request_data = client_socket.recv(4096).decode()
23   if not request_data:
24       print("最强王者已经下线了....")
25       client_socket.close()
26       return
27
28   # 4 解析请求报文 得到用户的资源请求路径  "GET /index2.html HTTP/1.1\r\n..."
29   # 4.1 切割请求报文 第0个元素就是请求行
30   request_line = request_data.split("\r\n")[0]
31   # 4.2 从请求行中提取出 用户资源请求路径
32   result = re.match(r"\w+\s+(\S+)", request_line)
33   if not result:
34       print("用户请求格式错误")
35       client_socket.close()
36       return
37
38   print("用户请求的路径是%s" % result.group(1))  # /home/python/Desktop/index.html
39   path_info = result.group(1)
40   # 当用户请求/ 表示首页  返回一个首页资源
41   if path_info == '/':
42       path_info = '/index.html'
43   response_header = "Server: PWS1.0\r\n"  # 响应头
44   # 5 读取对应资源 封装在HTTP响应报文中发送给浏览器
45   if not os.path.exists("static" + path_info):
46       response_line = "HTTP/1.1 404 Not Found\r\n"
47       with open("static/404.html", "rb") as file:
48           response_body = file.read()
49   else:
50       response_line = "HTTP/1.1 200 OK\r\n"  # 响应行 状态行
51
52       with open("static" + path_info, "rb") as file:
53           response_body = file.read()
54
55   response_data = (response_line + response_header + "\r\n").encode() + response_body
56   client_socket.sendall(response_data)
57
58   # 6 在合适的位置关闭套接字即可
59   client_socket.close()
60
61def main():
62   # 1 创建 绑定 监听套接字
63   server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
64   server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
65   server_socket.bind(('', 9999))
66   server_socket.listen(128)
67
68   # 2 不断地接受连接
69   while True:
70       client_socket, client_addr = server_socket.accept()
71       print("来自%s的最强王者上线了...." % str(client_addr))
72       # 当收到用户请求时, 启动一个协程来运行下面的函数
73       gevent.spawn(request_handler,client_socket)
74       # spawn创建协程并启动
75       # request_handler(client_socket)
76
77
78
79if __name__ == '__main__':
80   main()


2.3.6 面向对象

面向对象 每人的理解都不一样 面向对象  vs  面向过程 狗吃翔         吃狗翔

1from gevent import monkey
 2monkey.patch_all()   # 自动切换  recv accept time.sleep
 3import socket
 4import re
 5import os
 6import gevent
 7
 8"""
 9web服务作用:  接收请求报文 返回网页资源给web浏览器
10
11web服务器流程:
12   1 创建 绑定 监听套接字
13   2 接受连接
14   3 接收请求报文
15   4 解析请求报文 得到用户的资源请求路径
16   5 读取对应资源 封装在HTTP响应报文中发送给浏览器
17   6 在合适的位置关闭套接字即可
18"""
19
20class HTTPServer(object):
21   """web服务器类"""
22   def __init__(self):
23       """初始化  实例对象"""
24       # 1 创建 绑定 监听套接字
25       server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
26       server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
27       server_socket.bind(('', 9999))
28       server_socket.listen(128)
29       # 将套接字对象保存为当前对象
30       self.server_socket = server_socket
31   def start(self):
32       # 2 不断地接受连接
33       while True:
34           client_socket, client_addr = self.server_socket.accept()
35           print("来自%s的最强王者上线了...." % str(client_addr))
36           # 当收到用户请求时, 启动一个协程来运行下面的函数
37           gevent.spawn(self.request_handler, client_socket)
38           # spawn创建协程并启动
39           # request_handler(client_socket)
40   @staticmethod   # 装饰器
41   def request_handler(client_socket):
42       """这个函数用来处理客户端请求的"""
43       # 3 接收请求报文
44       request_data = client_socket.recv(4096).decode()
45       if not request_data:
46           print("最强王者已经下线了....")
47           client_socket.close()
48           return
49
50       # 4 解析请求报文 得到用户的资源请求路径  "GET /index2.html HTTP/1.1\r\n..."
51       # 4.1 切割请求报文 第0个元素就是请求行
52       request_line = request_data.split("\r\n")[0]
53       # 4.2 从请求行中提取出 用户资源请求路径
54       result = re.match(r"\w+\s+(\S+)", request_line)
55       if not result:
56           print("用户请求格式错误")
57           client_socket.close()
58           return
59
60       print("用户请求的路径是%s" % result.group(1))  # /home/python/Desktop/index.html
61       path_info = result.group(1)
62       # 当用户请求/ 表示首页  返回一个首页资源
63       if path_info == '/':
64           path_info = '/index.html'
65       response_header = "Server: PWS1.0\r\n"  # 响应头
66       # 5 读取对应资源 封装在HTTP响应报文中发送给浏览器
67       if not os.path.exists("static" + path_info):
68           response_line = "HTTP/1.1 404 Not Found\r\n"
69           with open("static/404.html", "rb") as file:
70               response_body = file.read()
71       else:
72           response_line = "HTTP/1.1 200 OK\r\n"  # 响应行 状态行
73
74           with open("static" + path_info, "rb") as file:
75               response_body = file.read()
76
77       response_data = (response_line + response_header + "\r\n").encode() + response_body
78       client_socket.sendall(response_data)
79
80       # 6 在合适的位置关闭套接字即可
81       client_socket.close()
82def main():
83   # 创建出一个web服务器类的实例对象
84   http_server = HTTPServer()
85   # 启动服务器运行
86   http_server.start()
87if __name__ == '__main__':
88   main()
89# 面向对象 每人的理解都不一样
90# 面向对象  vs  面向过程
91# 狗吃翔         吃狗翔


2.3.7 给web服务器添加命令行参数

耦合  功能与功能之间的关联程度

开发:解耦合

高内聚,低耦合

独立性   依赖性

sys.argv里面存放的是当前进程启动时的命令行参数

sys.argv是列表,每个元素是字符串

系统将命令行参数放进去的

1from gevent import monkey
 2monkey.patch_all()   # 自动切换  recv accept time.sleep
 3import socket
 4import re
 5import os
 6import gevent
 7import sys
 8"""
 9web服务作用:  接收请求报文 返回网页资源给web浏览器
10
11web服务器流程:
12   1 创建 绑定 监听套接字
13   2 接受连接
14   3 接收请求报文
15   4 解析请求报文 得到用户的资源请求路径
16   5 读取对应资源 封装在HTTP响应报文中发送给浏览器
17   6 在合适的位置关闭套接字即可
18"""
19
20class HTTPServer(object):
21   """web服务器类"""
22   def __init__(self,port):
23       """初始化  实例对象"""
24       # 1 创建 绑定 监听套接字
25       server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
26       server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
27
28       server_socket.bind(('',port))
29       server_socket.listen(128)
30       # 将套接字对象保存为当前对象
31       self.server_socket = server_socket
32   def start(self):
33       # 2 不断地接受连接
34       while True:
35           client_socket, client_addr = self.server_socket.accept()
36           print("来自%s的最强王者上线了...." % str(client_addr))
37           # 当收到用户请求时, 启动一个协程来运行下面的函数
38           gevent.spawn(self.request_handler, client_socket)
39           # spawn创建协程并启动
40           # request_handler(client_socket)
41   @staticmethod   # 装饰器
42   def request_handler(client_socket):
43       """这个函数用来处理客户端请求的"""
44       # 3 接收请求报文
45       request_data = client_socket.recv(4096).decode()
46       if not request_data:
47           print("最强王者已经下线了....")
48           client_socket.close()
49           return
50
51       # 4 解析请求报文 得到用户的资源请求路径  "GET /index2.html HTTP/1.1\r\n..."
52       # 4.1 切割请求报文 第0个元素就是请求行
53       request_line = request_data.split("\r\n")[0]
54       # 4.2 从请求行中提取出 用户资源请求路径
55       result = re.match(r"\w+\s+(\S+)", request_line)
56       if not result:
57           print("用户请求格式错误")
58           client_socket.close()
59           return
60
61       print("用户请求的路径是%s" % result.group(1))  # /home/python/Desktop/index.html
62       path_info = result.group(1)
63       # 当用户请求/ 表示首页  返回一个首页资源
64       if path_info == '/':
65           path_info = '/index.html'
66       response_header = "Server: PWS1.0\r\n"  # 响应头
67       # 5 读取对应资源 封装在HTTP响应报文中发送给浏览器
68       if not os.path.exists("static" + path_info):
69           response_line = "HTTP/1.1 404 Not Found\r\n"
70           with open("static/404.html", "rb") as file:
71               response_body = file.read()
72       else:
73           response_line = "HTTP/1.1 200 OK\r\n"  # 响应行 状态行
74
75           with open("static" + path_info, "rb") as file:
76               response_body = file.read()
77
78       response_data = (response_line + response_header + "\r\n").encode() + response_body
79       client_socket.sendall(response_data)
80
81       # 6 在合适的位置关闭套接字即可
82       client_socket.close()
83def main():
84   # sys.argv对象  存储的是 当前进程运行的命令参数 的列表 每个元素都是字符串
85   # 如果说数量属于2个(缺端口) 或者 端口数据不是数字字符构成的
86
87   if len(sys.argv) < 2 or not sys.argv[1].isdigit():
88       print("参数使用错误 usage:python3 添加命令行参数指定端口.py 8888")
89       return
90   port = int(sys.argv[1])
91   # 创建出一个web服务器类的实例对象
92   http_server = HTTPServer(port)
93   # 启动服务器运行
94   http_server.start()
95if __name__ == '__main__':
96   main()


相关文章
|
1月前
|
XML 前端开发 JavaScript
PHP与Ajax在Web开发中的交互技术。PHP作为服务器端脚本语言,处理数据和业务逻辑
本文深入探讨了PHP与Ajax在Web开发中的交互技术。PHP作为服务器端脚本语言,处理数据和业务逻辑;Ajax则通过异步请求实现页面无刷新更新。文中详细介绍了两者的工作原理、数据传输格式选择、具体实现方法及实际应用案例,如实时数据更新、表单验证与提交、动态加载内容等。同时,针对跨域问题、数据安全与性能优化提出了建议。总结指出,PHP与Ajax的结合能显著提升Web应用的效率和用户体验。
48 3
|
2月前
|
Java PHP
PHP作为广受青睐的服务器端脚本语言,在Web开发中占据重要地位。理解其垃圾回收机制有助于开发高效稳定的PHP应用。
【10月更文挑战第1天】PHP作为广受青睐的服务器端脚本语言,在Web开发中占据重要地位。其垃圾回收机制包括引用计数与循环垃圾回收,对提升应用性能和稳定性至关重要。本文通过具体案例分析,详细探讨PHP垃圾回收机制的工作原理,特别是如何解决循环引用问题。在PHP 8中,垃圾回收机制得到进一步优化,提高了效率和准确性。理解这些机制有助于开发高效稳定的PHP应用。
53 3
|
4月前
|
API C# 开发框架
WPF与Web服务集成大揭秘:手把手教你调用RESTful API,客户端与服务器端优劣对比全解析!
【8月更文挑战第31天】在现代软件开发中,WPF 和 Web 服务各具特色。WPF 以其出色的界面展示能力受到欢迎,而 Web 服务则凭借跨平台和易维护性在互联网应用中占有一席之地。本文探讨了 WPF 如何通过 HttpClient 类调用 RESTful API,并展示了基于 ASP.NET Core 的 Web 服务如何实现同样的功能。通过对比分析,揭示了两者各自的优缺点:WPF 客户端直接处理数据,减轻服务器负担,但需处理网络异常;Web 服务则能利用服务器端功能如缓存和权限验证,但可能增加服务器负载。希望本文能帮助开发者根据具体需求选择合适的技术方案。
216 0
|
4月前
|
Rust 安全 开发者
惊爆!Xamarin 携手机器学习,开启智能应用新纪元,个性化体验与跨平台优势完美融合大揭秘!
【8月更文挑战第31天】随着互联网的发展,Web应用对性能和安全性要求不断提高。Rust凭借卓越的性能、内存安全及丰富生态,成为构建高性能Web服务器的理想选择。本文通过一个简单示例,展示如何使用Rust和Actix-web框架搭建基本Web服务器,从创建项目到运行服务器全程指导,帮助读者领略Rust在Web后端开发中的强大能力。通过实践,读者可以体验到Rust在性能和安全性方面的优势,以及其在Web开发领域的巨大潜力。
47 0
|
4月前
|
Java 数据库 API
JSF与JPA的史诗级联盟:如何编织数据持久化的华丽织锦,重塑Web应用的荣耀
【8月更文挑战第31天】JavaServer Faces (JSF) 和 Java Persistence API (JPA) 分别是构建Java Web应用的用户界面组件框架和持久化标准。结合使用JSF与JPA,能够打造强大的数据驱动Web应用。首先,通过定义实体类(如`User`)和配置`persistence.xml`来设置JPA环境。然后,在JSF中利用Managed Bean(如`UserBean`)管理业务逻辑,通过`EntityManager`执行数据持久化操作。
63 0
|
2月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
169 3
|
1月前
|
设计模式 前端开发 数据库
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第27天】本文介绍了Django框架在Python Web开发中的应用,涵盖了Django与Flask等框架的比较、项目结构、模型、视图、模板和URL配置等内容,并展示了实际代码示例,帮助读者快速掌握Django全栈开发的核心技术。
184 45
|
22天前
|
前端开发 安全 JavaScript
2025年,Web3开发学习路线全指南
本文提供了一条针对Dapp应用开发的学习路线,涵盖了Web3领域的重要技术栈,如区块链基础、以太坊技术、Solidity编程、智能合约开发及安全、web3.js和ethers.js库的使用、Truffle框架等。文章首先分析了国内区块链企业的技术需求,随后详细介绍了每个技术点的学习资源和方法,旨在帮助初学者系统地掌握Dapp开发所需的知识和技能。
2025年,Web3开发学习路线全指南
|
29天前
|
存储 前端开发 JavaScript
如何在项目中高效地进行 Web 组件化开发
高效地进行 Web 组件化开发需要从多个方面入手,通过明确目标、合理规划、规范开发、加强测试等一系列措施,实现组件的高效管理和利用,从而提高项目的整体开发效率和质量,为用户提供更好的体验。
32 7
|
1月前
|
开发框架 搜索推荐 数据可视化
Django框架适合开发哪种类型的Web应用程序?
Django 框架凭借其强大的功能、稳定性和可扩展性,几乎可以适应各种类型的 Web 应用程序开发需求。无论是简单的网站还是复杂的企业级系统,Django 都能提供可靠的支持,帮助开发者快速构建高质量的应用。同时,其活跃的社区和丰富的资源也为开发者在项目实施过程中提供了有力的保障。