web-server-面向对象动态

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()
view Code

 

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()]
application Code

 

tcpIO多路复用服务器epoll版

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()
View Code

 

tcp轮询服务器

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()
View Code

 

posted @ 2017-08-28 21:35  凯哥吧  阅读(120)  评论(0编辑  收藏  举报