python建造的简单版web服务器的第二个版本,其中有几个验证的例子。我将在下面列出。
第一部分 :web服务器的代码:
import socket,multiprocessing,re
class HTTPServer():
def __init__(self,application):
self.sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.application = application
def start(self):
"""开始创建链接收发数据"""
self.sock.listen(128)
while True:
#创建一个连接
user_name,user_ip = self.sock.accept()
user_process = multiprocessing.Process(target=self.hand_clien,args=(user_name,))
user_process.start()
user_name.close()
def start_response(self,status,headers):
"""组合成要返回的头部信息"""
response_headers = "HTTP/1.1 " + status + "\n"
for lin in headers:
response_headers += "%s: %s"%lin
self.response_headers = response_headers
def hand_clien(self,user_name):
"""拿到请求的数据"""
#存在一个bug 这个bug是当进程其中一个被销毁另一个再去拿数据就会报错
user_data = user_name.recv(1024).decode('utf-8')
request_date = user_data.splitlines()
request_date_startline = request_date[0]
#提取用户要搜索的名字
file_neme = re.match(r"\w+ +(/[^ ]*)",request_date_startline).group(1)
method = re.match(r"(\w+) +/[^ ]* ", request_date_startline).group(1)
env = {
"PATH_INFO": file_neme,
"METHOD": method
}
#调用要访问的文件或函数返回bady数据 同时将本类中的字典还有函数传过去
response_body = self.application(env,self.start_response)
#组合成要发给用户的数据格式
response = self.response_headers + "\n\n" + response_body
user_name.send(response.encode('utf-8'))
user_name.close()
def server(self,prot):
"""设置服务器端口"""
self.sock.bind(("", prot))
第二部分 :farmework用户启动部分里面包含了一个sayhello的页面 还有解析主页的方法:
from FiveDemo.ThreeDemo import HTTPServer
import time
#此处引入hehehe是一个.py的文件 验证了eval的使用引入法
#引入时要将文件夹一块引入
import FiveDemo.hehehe
class Application():
def __init__(self,urls):
self.urls = urls
def __call__(self, env, start_response):
path = env.get("PATH_INFO","/")
for url,header in self.urls:
if path == url:
try:
#此处用eval将字符串转化为函数
new_header = eval(header)
return new_header(env,start_response)
except Exception:
stauts = "404 Not Found"
header = []
start_response(stauts, header)
return "Server down"
stauts = "404 Not Found"
header = []
start_response(stauts,header)
return "404 Not Found"
def sayhelll(env,start_response):
stauts = "200 OK"
header = [("Server","Text")]
start_response(stauts,header)
return time.ctime()
def readHtml(env,start_response):
"""这个方法的是负责主页的 负责读html文件"""
stauts = "200 OK"
header = [("Server", "Text")]
try:
file = open("Hello.html", "rb")
except Exception:
pass
else:
respones_bady = file.read()
start_response(stauts, header)
file.close()
return respones_bady.decode('utf-8')
def main():
"""在写urls时如果我想引入外面的一个文件(hehehe.py)时发现报没有定义的错 我只能定义成字符串然后采用eval将字符串转成函数名 在上面引入这个文件就可以访问了sayhello 直接在这里面定义的可以直接写 但是因为上面采用了eval就不能在直接写成函数名了采用字符串的形式sayhello也是可以直接读取的"""
urls = [("/sayhelll","sayhelll"),("/hehehe","FiveDemo.hehehe.application"),("/","readHtml")]
app = Application(urls)
httpserver = HTTPServer(app)
httpserver.server(7878)
httpserver.start()
if __name__ == '__main__':
main()
第三部分 :创建所在目录创建一个Hello.html的文件作为主页,内容是随意的
第四部分 :在本地创建一个名为hehehe.py python脚本代码如下:
import time
#这里的简单的返回当前的时间
def application(evn,start_respones):
state = '200 OK'
headers = [
("Content-Type", "text/plain")
]
start_respones(state,headers)
return time.ctime()