需求:
通过pythontcp网络传输方式、http通信协议、正则表达式、多任务协程等知识点完成http协议的web静态服务器,采用面向对象的方式进行编程,实现多任务方式完成不同浏览器同时访问的需求。
ps:代码中涉及几个网页页面需要提前建立,并在代码中修改路径。
代码:
import socket
import re
import gevent
from gevent import monkey
# 打补丁,捕获任务停顿
monkey.patch_all()
# 创建web服务器类
class TcpSeverPlay(object):
# 定义web服务器属性
def __init__(self):
# 建立一个tcp网络通讯方式的通讯链接
tcp_sever_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 端口释放
tcp_sever_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定服务器ip及端口
tcp_sever_socket.bind(('', 9090))
# 设置监听及最大等待链接数
tcp_sever_socket.listen(128)
# 声明tcp_sever_socket属性
self.tcp_sever_socket = tcp_sever_socket
def start(self):
# 建立循环访问
while True:
# 设置变量接受客户端的通讯链接及ip地址
sever_client_socket, ip_port = self.tcp_sever_socket.accept()
# 创建协程
gevent.spawn(self.sever_founc, sever_client_socket)
@staticmethod
# 协程实现多任务
def sever_founc(sever_client_socket):
# 接收客户端发送的请求报文
recv_request_data = sever_client_socket.recv(4096)
# 对接收的二进制报文进行解码
recv_request = recv_request_data.decode('utf-8')
# 打印请求报文
print(recv_request)
# 提取请求报文中的请求资源路径
file_line_re = re.search('/\S*', recv_request)
file_line = file_line_re.group()
# 判断请求路径是否为‘/’,如果是,则定向到指定的主界面
if file_line == '/':
file_line = '/index.html'
# 用异常判断如果请求的路径不存在,返回404响应报文
try:
# 在目录下打开请求资源路径指引的文件
with open('static' + file_line, 'rb')as file:
# 读取文件内容并写入响应体
response_body = file.read()
except Exception as e:
# 指定响应体404路径
with open('static/404.html', 'rb')as file:
# 读取文件内容并写入响应体
response_body = file.read()
# 建立404响应报文的格式及内容
# 响应行:
response_line = 'HTTP/1.1 404.html NOT FOUND\r\n'
# 响应头:
response_header = 'Host: WWS/1.1\r\nlog:1\r\n'
# 拼装响应报文并编码:
send_response_data = (response_line + response_header + '\r\n').encode('utf-8') + response_body
# 发送响应报文
sever_client_socket.send(send_response_data)
else:
# 建立响应报文的格式及内容
# 响应行:
response_line = 'HTTP/1.1 200 OK\r\n'
# 响应头:
response_header = 'Host: WWS/1.1\r\nlog:1\r\n'
# 拼装响应报文并编码:
send_response_data = (response_line + response_header + '\r\n').encode('utf-8') + response_body
# 发送响应报文
sever_client_socket.send(send_response_data)
finally:
# 关闭此次链接
sever_client_socket.close()
# 测试
if __name__ == '__main__':
# 创建一个服务器对象
g1 = TcpSeverPlay()
# 启动这个服务器对象
g1.start()