? 接前文,如果只在网页显示hahaha毫无意义,所以本文将在浏览器上显示网页
? ps:本文所用html文件来自度娘和b站的html源码。
1.主程序部分与前文没有差别,关键区别在于服务器的方法中。
2.浏览器请求网页时,在地址栏可以输入ip:port/xxx.html,其中xxx.html是可以缺省的项。而该项正是浏览器所请求的页面。
3.xxx.html在http请求报文中处于header的第一行,所以我们需要让服务器得到这个文件名,才能打开对应的文件。
4.获取文件名需要用到字符串的拆分,正则匹配。
5.打开文件需要捕获异常,防止服务器崩溃。
6.同时加入了多进程,实现多任务服务器
? ? ? ? 父子进程不共享全局变量,它们的服务套接字变量连接了os底层的同一个文件描述符,是硬连接,单独关闭一个并不影响另一个,只有都close才会彻底关闭套接字。
7.由于进程耗费资源大,在大量用户访问的情况下,协程更优
8.代码如下
import socket
import re
import gevent
from gevent import monkey
monkey.patch_all()
def serve_func(c_sock):
# 接收服务器请求,并解码
c_data = c_sock.recv(1024).decode("utf-8")
# 拆分字符串,返回一个列表
c_list = c_data.splitlines()
# 取列表第0项进行正则匹配
# 正则匹配含义:第一个字符集中除了/有至少一个字符
# /之后,第二个字符集中除了空格可以有任意个字符
# GET /xxx.html HTTP/1.1
result = re.match(r"[^/]+(/[^ ]*)", c_list[0])
# 小括号是为了用group取出第一个小括号里的内容
# 如果匹配变量为真
if result:
# 获取网页名称
file_name = result.group(1)
# 如果网页名称为空
if len(file_name) == 0:
# 返回一个固定网页,类似于首页
file_name == /baidu.html
# 尝试打开文件
try:
f = open("./Desktop" + file_name, "r", encoding=("utf-8"))
# 打开失败返回404not found
except:
res = "HTTP/1.1 404 not found\r\n\r\n"
res += "<h1>Not Found</h1>"
c_sock.send(res.encode("utf-8"))
# 打开成功则将文件内容发送给浏览器
else:
f_content = f.read()
f.close()
res2 = "HTTP/1.1 200 OK\r\n\r\n"
res2 += f_content
c_sock.send(res2.encode("utf-8"))
# 关闭服务套接字
t_sock.close()
def main():
# 创建tcp套接字
tcp_sock = socket.socket(socket.AF_INET, socket.STREAM)
# 绑定地址
tcp_sock.bind(('', 54321))
# 把套接字转为监听模式
tcp_sock.listen(128)
# 循环服务
while True:
# 使用accept等待客户端连接
# 连接成功后返回服务套接字和客户端地址
client_sock, client_add = tcp_sock.accept()
# 创建协程
p = gevent.spawn(serve, client_sock)
# 关闭监听套接字
tcp_sock.close()
if __name__ == "__main__":
main()
|