import socketimport reimport osimport sys# 由于前面太繁琐,可以用类封装一下,也可以分几个模块class HttpServer(object):def __init__(self,port):# 1、服务器创建负责监听的socketself.socket_watch = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 2、设置地址重用self.socket_watch.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)# 3、绑定监听的端口self.socket_watch.bind(('', port))# 4、设置监听队列self.socket_watch.listen(128)def handle_client(self,socket_con):"""接收来自客户端的请求,并接收请求报文,解析,返回"""# 1、服务器接收客户端的请求报文request = socket_con.recv(4096).decode()# 2、截取请求报文,获取请求行request_lines = request.split("\r\n")# 3、获取请求行request_line = request_lines[0]# GET /a/ab/c.html HTTP/1.1# 通过正则表达式 匹配出请求行中请求资源路径res = re.match(r"\w+\s+(\S+)",request_line)# 获取资源路径path = res.group(1)# 将资源路径和我的web文件夹的绝对路径拼接(自己填写)path ="# 本地绝对路径" + path# 在判断是文件还是文件夹之前,首先要判断你这个路径在服务器中是否存在if not os.path.exists(path):response_line = 'HTTP/1.1 404 Not Found\r\n'response_head = 'Server:skylark 2.0\r\n'response_head += 'Content-type:text/html;charset=utf-8\r\n'response_body = '你请求'+ path +'不存在'response = response_line + response_head + '\r\n' +response_bodysocket_con.send(response.encode())socket_con.close()returnelse:# 判断用户请求的是文件还是文件夹if os.path.isfile(path):# 如果文件存在 读取页面数据,然后返回response_line = "HTTP/1.1 200 OK\r\n"response_head = "Server:skylark 2.0\r\n"# 注意请求图片需要使用"rb"的方式进行读取file = open(path,"rb")# response_body 是二进制所以不用再次编码response_body = file.read()response = response_line.encode() + response_head.encode() +"\r\n".encode() +response_bodysocket_con.send(response)socket_con.close()returnelse:if path.endswith("/"):# 例如 /images# 用户请求的文件夹# 1、判断该文件夹下是否有默认的文件,如果有,则返回,如果没有# index.html default.htmldefault_document = False# 如果允许你访问我目录下的默认文档if default_document:# 判断用户访问的文件夹下是否有index.html 或者 default.htmlif os.path.exists(path + '/index.html'):response_line = 'HTTP/1.1 200 OK\r\n'response_head = 'Server:skylark 2.0\r\n'file = open(path+'/index.html', 'rb')response_body = file.read()response = response_line.encode() + response_head.encode() +'\r\n'.encode()+response_bodysocket_con.send(response)socket_con.close()returnelif os.path.exists(path + '/default.html'):response_line = 'HTTP/1.1 200 OK\r\n'response_head = 'Server:skylark 2.0\r\n'file = open(path + '/default.html', 'rb')response_body = file.read()response = response_line.encode() + response_head.encode() + '\r\n'.encode() + response_bodysocket_con.send(response)socket_con.close()returnelse:# 访问的目录下,既没有index.html 也没有default.htmlresponse_line = 'HTTP/1.1 404 Not Found\r\n'response_head = 'Server:skylark 2.0\r\n'response_head += 'Content-Type:text/html;charset=utf-8\r\n'response_body = 'index.html 或者 default.html 不存在'response = response_line +response_head +'\r\n' +response_bodysocket_con.send(response.encode())socket_con.close()# 2、判断服务器是否开启了目录浏览else:# 判断你是否开启了目录浏览dir_browsing = Trueif dir_browsing:# 把用户请求的文件夹中所有的文件和文件夹以目录的形式返回到页面中# 获取用户请求的文件夹list_names = os.listdir(path)response_line = 'HTTP/1.1 200 OK\r\n'response_head = 'Server:skylark 2.0\r\n'# 动态的拼接页面,将目录中的文件或者文件夹的名称以HTML页面的方式返回给浏览器response_body = '<html><head><body><ul>'for item in list_names:response_body +="<li><a href = '#'>"+item+"</a></li>"response_body+='</ul></body></head></html>'response =response_line + response_head +'\r\n' +response_bodysocket_con.send(response.encode())socket_con.close()returnelse:# 用户请求的路径没有斜线# 重定向到+斜线的目录下response_line = 'HTTP/1.1 302 Found\r\n'response_head = 'Server:skylark 2.0\r\n'response_body = 'redirect'+ path +'/'response = response_line +response_head +'\r\n' +response_bodysocket_con.send(response.encode())socket_con.close()def run_server(self):# 5、通过循环,不停的接收来自客户端的连接请求while True:socket_con, con_adds = self.socket_watch.accept()# 注意将con_adds转成字符串print('客户端:%s连接成功!!!' % str(con_adds))# 接收来自客户端的请求,并接收请求报文,解析,返回self.handle_client(socket_con)def main():# sys.argv方法的用法如下:# 在终端输入 python3 面向对象封装的web服务器.py 8888# 在使用解释器执行任意py文件的时候,可以传入不止一个参数,会以字符串的形式用列表保存起来# 但是列表的第一个参数[0]位是它自己。所以传入的参数是从[1]第二位开始的# 所以在上面输入8888以后,调取这个列表的[1]下标就会传入这个8888作为进到下面的代码# 再转换一下类型为int就相当于用户指定端口了port = int(sys.argv[1])http_server = HttpServer(port)http_server.run_server()if __name__ == '__main__':main()
1500字范文,内容丰富有趣,写作好帮手!