web-server-面向对象动态
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import socket from multiprocessing import Process import re import sys class MyHttpServer(object): """定义服务器类""" def __init__(self, server_addr): # 创建socket 用于监听 self.listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 设置允许 self.listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 绑定ip self.listen_socket.bind(server_addr) # 进入监听 self.listen_socket.listen(128) print("listen....") def start_service(self): """启动任务函数""" # 等待 while 1: # 等待建立连接 new_socket, peer_ip = self.listen_socket.accept() print("ip:%s connect..." % str(peer_ip)) # 创建进程 process_server = Process(target=self.handle_client, args=(new_socket,)) # 启动进程 process_server.start() # 关闭新创建的套接字 new_socket.close() # 关闭监听套接字 listen_socket.close() def handle_client(self, new_socket): """完成客户端任务的创建""" # 接受客户端的数据 recv_data = new_socket.recv(1024) # 判断关闭 if len(recv_data) == 0: print('ip:%s close....' % str(new_socket.getpeername())) return # 对客户端发送的请求进行处理 # 1.获取到数据的每行信息 request_data = recv_data.decode("gbk").splitlines() # 2.提取到请求行 request_line = request_data[0] # 3.提取请求行的文件 GET / HTTP/1.1 request_file = re.match("(GET|POST) (/.*) HTTP/1.1", request_line).group(2) # 判断用户输入访问的文件是否是已.py结尾 注意if 后面的not if not request_file.endswith(".py"): # 根据用户请求的内容给做回复 # 1.将用户输入的路径转换成在本地可以找到的路径 # 如果是/ 默认是起始页 if request_file == "/": request_file = "/index.html" # 2.转换成本地路径 request_file = HTML_dir + request_file # 读取文件将文件内容发送 # 文件可能不存在 不存在时就会报错 所以异常处理 try: file_obj = open(request_file, "rb") except IOError as e: print(e) # 当文件不存在时 response_statue_lines = b"HTTP/1.1 404\r\n" response_header = b"" response_body = b"Not Found" else: # 发送消息给客户端 # 1.状态行 response_statue_lines = b"HTTP/1.1 200 OK\r\n" # 2.相应头 response_header = b"Content-Type:text/html; charset=UTF-8\r\n" # response_header = b"Content-Type:text/plain; charset=UTF-8\r\n" 以txt文本显示 # 3.响应体 response_body = file_obj.read() # 因为是以二进制的方式读取 所以不需要编码发送 为 # 了统一 所以将所有的发送内容前面加b 转成二进制 finally: # 4.拼接 response = response_statue_lines + response_header + b"\r\n" + response_body # 发送 new_socket.send(response) # 关闭新创建的套接字 new_socket.close() # 以.py结尾时 动态资源访问 else: evn = {} # 调用外部导入的函数传输规定的参数 列表和 获取 状态行,响应头的方法 返回响应体 response_body = self.application(evn, self.start_response) # 调用发送响应功能 self.finish(response_body, new_socket) def start_response(self, statue, response_headers): """完成获取状态行和响应头的功能""" self.headers_list = [statue, response_headers] def set_application(self, application): """完成获取玩不函数的引用""" self.application = application def finish(self, response_body, new_socket): """完成拼接响应内容,和发送响应的功能""" statue, response_headers = self.headers_list response = "HTTP/1.1 " + statue +"\r\n" # 组装响应头 for header in response_headers: response += ("%s:%s\r\n" % (header[0], header[1])) # response += ("%s:%s" % (key, value)) # 响应头和响应体的空格 response += "\r\n" # 组装响应体 for body in response_body: response += body # 发送 关闭 new_socket.send(response.encode()) new_socket.close() # 设置默认寻找路径 HTML_dir = "./html2" PYTHON_DIR = "./wsgispy" def main(): # 获取执行程序是传递的参数 print(sys.argv) if len(sys.argv) < 2: # 模块: 函数 sys.exit("Usage %s module:application" % sys.argv[0]) # 获取到argv的参数 app_path = sys.argv[1] # 获取到的参数是module:application 进行处理 module, application = app_path.split(":") # 将当前路径的wsgispy加入系统查找列表当中 sys.path.insert(0, PYTHON_DIR) # 将字符串转程 模块对象 module = __import__(module) # 将函数转成函数对象 application = getattr(module, application) # 定义地址 server_addr = ("", 10000) # 创建对象 Httpd = MyHttpServer(server_addr) # 调用类中或取application的方法 Httpd.set_application(application) # 调用启动方法 Httpd.start_service() if __name__ == '__main__': main()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import time def app(evn, start_statue): """ 完成动态获取消息 :param evn: 字典 :param start_statue: 服务器传送来的方法 用来将状态行和响应头发送过去 :return: 返回响应体 """ statue = "200 OK" response_headers = [("Content-Type", "text/plain"), ("Server", "MyHttpServer")] start_statue(statue, response_headers) return [str(evn) + "欢迎来到凯哥的WSGI动态世界 %s" % time.ctime()]
tcpIO多路复用服务器epoll版
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import socket import select def main(): # 创建tcp监听 listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 设置重用 listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 绑定 my_addr = ("192.168.0.117", 10000) listen_socket.bind(my_addr) # 进入监听 listen_socket.listen(128) print("listen.....") # 创建灯 my_epoll = select.epoll() # 注册灯 my_epoll.register(listen_socket.fileno(), select.EPOLLIN | select.EPOLLET) # 创建字典,,用来存储新创建的套接字 socket_dick = {} while 1: # 启动灯 # 注册灯以后 谁有信号我找谁 默认将epoll启动后为 阻塞模式 ready_fd_list = my_epoll.poll() for fd, enent in ready_fd_list: # 判断是否为监听套接字的信号灯 if fd == listen_socket.fileno(): new_socket, peer_ip = listen_socket.accept() print("ip:%s connect..." % str(peer_ip)) my_epoll.register(new_socket.fileno(), select.EPOLLIN | select.EPOLLET) socket_dick[new_socket.fileno()] = new_socket # 为新创建的监听套接字 else: # 根据fd取对应的套接字 sock = socket_dick[fd] recv_data = sock.recv(1024) if recv_data: print("ip:%s---->%s" % (str(sock.getpeername()), recv_data.decode("gbk"))) else: print("ip:%s close..." % str(sock.getpeername())) sock.close() my_epoll.unregister(fd) del socket_dick[fd] listen_socket.close() if __name__ == '__main__': main()
tcp轮询服务器
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import socket import time def main(): listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 设置一分钟之内重用端口 listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) my_addr = ("192.168.0.117", 8080) listen_socket.bind(my_addr) # 将监听模式设置为非阻塞 当没有请求时会报错 listen_socket.setblocking(False) listen_socket.listen(128) print("listen....") # 当有套接字产生时存放到列表当中 socket_list = [] while 1: try: # 设置监听套接字 new_sock, peer_ip = listen_socket.accept() except: pass else: print("ip:%s connect....." % str(peer_ip)) # 将连接的套接字添加到列表当中 socket_list.append(new_sock) # 将新连接的套接字设置为非阻塞模式 new_sock.setblocking(False) # 定义一个列表当客户端关闭时将该套接字存放到该列表当中 need_delete_socket = [] # 遍历socket_list当中的每个套接字是否由发来的消息 for sock in socket_list: try: # 发消息时接受消息,没有消息就会报错 recv_data = sock.recv(1024) except: pass else: if recv_data: # 如果由消息打印 print("ip:%s---->%s" % (str(sock.getpeername()), recv_data.decode("gbk"))) else: # 为空时关闭 并将该套接字添加到删除列表当中 print("ip:%s close...." % str(sock.getpeername())) need_delete_socket.append(sock) sock.close() # 遍历需要删除的列表从socket_list当中删除 for sock in need_delete_socket: socket_list.remove(sock) # print(socket_list) # print(need_delete_socket) # time.sleep(3) listen_socket.close() if __name__ == '__main__': main()