导入必要的模块
代码语言:javascript复制import re
import socket
from multiprocessing import Process
我们导入了re模块用于正则表达式操作,socket模块用于网络通信,以及multiprocessing模块中的Process类用于创建子进程
定义WSGIServer类
代码语言:javascript复制class WSGIServer():
def __init__(self, server, port, root):
self.server = server
self.port = port
self.root = root
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server_socket.bind((self.server, self.port))
self.server_socket.listen(128)
在类的初始化方法__init__中,我们传入了服务器地址server、端口号port和根目录root作为参数,然后创建了一个socket对象server_socket,并设置了一些属性。我们通过bind方法将服务器地址和端口号绑定到server_socket上,并调用listen方法监听连接请求。
处理客户端请求
代码语言:javascript复制def handle_socket(self, socket):
data = socket.recv(1024).decode('utf-8').splitlines()[0]
file_name = re.match(r'[^/] (/[^ ]*)', data)[1]
if file_name == '/':
file_name = self.root '/index.html'
else:
file_name = self.root file_name
try:
file = open(file_name, 'rb')
except IOError:
response_header = 'HTTP/1.1 404 NOT FOUND rn'
response_header = 'rn'
response_body = '========Sorry,file not found======='.encode('utf-8')
else:
response_header = 'HTTP/1.1 200 OK rn'
response_header = 'rn'
response_body = file.read()
finally:
socket.send(response_header.encode('utf-8'))
socket.send(response_body)
接下来定义了一个handle_socket方法,用于处理客户端发来的请求。首先,我们通过socket.recv方法接收请求数据,并对数据进行解码。然后,使用正则表达式从请求数据中提取出文件名。如果文件名为根目录’/',我们将其设置为根目录下的’index.html’文件,否则拼接上根目录路径。然后,尝试打开对应的文件,如果文件不存在,我们返回404状态码和错误提示信息;如果文件存在,我们返回200状态码和文件内容作为响应体。 最后,我们通过finally块使用socket.send方法将响应头和响应体发送给客户端。
持续监听连接请求
代码语言:javascript复制def forever_run(self):
while True:
client_socket, client_addr = self.server_socket.accept()
p = Process(target=self.handle_socket, args=(client_socket,))
p.start()
client_socket.close()
在WSGIServer类中,定义了一个forever_run方法,用于持续监听连接请求。在循环中,我们使用accept方法接受客户端的连接请求,并创建一个子进程Process去处理连接请求,以实现多线程并发处理。然后关闭客户端套接字。
主程序入口
代码语言:javascript复制if __name__ == '__main__':
ip = '0.0.0.0'
port = 8899
server = WSGIServer(ip, port, './pages')
print('server is running at {}:{}'.format(ip, port))
server.forever_run()
在主程序中,我们实例化了WSGIServer类,并传入服务器地址、端口号和根目录的参数。然后打印出服务器运行的信息,最后调用forever_run方法开始监听连接请求。