您的位置:首页 > 编程语言 > Python开发

python3 简单实现 web 静态服务器

2017-11-21 21:27 841 查看
from gevent import monkey
monkey.patch_all()
import re
import gevent
from socket import *

class HttpServer(object):
"""HTTP服务器类"""
def __init__(self):
# 创建一个TCP的监听套接字 ,接受客户端的连接请求
self.server_sock = socket(AF_INET, SOCK_STREAM)
# 地址重设 , 在重启的时候能立即释放端口, 1 表示设置 0 表示取消设置
self.server_sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
# 绑定端口
self.server_sock.bind(('', 7724))
# 将主动套接字转变为被动套接字
self.server_sock.listen(128)

def start(self):
# 循环接受客户端请求
while True:
client_sock, client_adr = self.server_sock.accept()
print("收到来自%s的请求" % str(client_adr))
# 创建并启动协程
# 破解patch_all ----> recv,recvfrom,accept 如果没有数据 就能够自动被gevent自动切换
gevent.spawn(self.handle_client, client_sock)

def handle_client(self, client_socket):
# 接受客户端的HTTP报文 ---数据
rec_data = client_socket.recv(4096).decode()
# 判断如果接受的数据为空, 即客户端断开连接
if not rec_data:
client_socket.close()
print("客户端断开了连接")
return
# 拆分出请求报文的每一行 返回一个列表
data_list = rec_data.splitlines()
# 解析用户的请求路径 ,获取请求行数据 第0行
request_line = re.match(r"\w+\s+(\S+)", data_list[0])
# 如果输入的地址有误 ,断开连接
if not request_line:
# 表明请求的格式不合法
client_socket.close()
print("输入的地址有误")
return
# 格式合法 根据正则提取出用户请求的路径信息
path_info = request_line.group(1)
# 当用户访问"/"时 ,自动跳转到 "/index.html"
if path_info == "/":
# index.html 一般代表一个网站的首页
path_info = "/index.html"

try:
# 以二进制方式打开文件,文件的目录=服务器指定的目录+用户请求的目录, 读取的文件类型是bytes类型
with open("static" + path_info, "rb") as file:
file_content = file.read()
except Exception as e:
# 如果用户请求的路径不存在 则会抛出404 不存在 错误
response_data = "HTTP/1.1 404 NOT FOUND\r\n"
# 头部数据
response_data += "server: Python Server Hyper1.0\r\n"
# 空行
response_data += "\r\n"
# 响应体数据 根据响应报文的格式 拼接相关数据
response_data += "404NOTFOUND" * 1000
# 将响应体数据编码发送
client_socket.send(response_data.encode())
else:
# 打开文件成功  文件数据就是响应体数据
response_data = "HTTP/1.1 200 OK\r\n"
response_data += "server: Python Server Hyper1.0\r\n"
response_data += "\r\n"
# 如果响应的文件数据是图片,音频, 视频的等二进制资源 ,则不能进行decode操作
response_body = response_data.encode() + file_content
# send函数返回值的含义是表示成功发送的字节数,如果想要全部发送, 可以使用sendall
client_socket.send(response_body)
finally:
# 不管有无发生异常,都会执行套接字关闭
client_socket.close()

def main():
# 创建一个HttpServer的实例对象
http_server = HttpServer()
# 开始启动http_server
http_server.start()

if __name__ == '__main__':
main()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息