Python 使用非阻塞原理实现tcp服务器多线程,并用系统epoll改进tcp服务器,实现高效并发 两份源码!

""" 除了使用进程池,线程,协程外.   可以考虑使用非堵塞原理实现tcp服务器多线程,并用系统epoll改进tcp服务器"""

#一._tcp端服务器线程面向非堵塞

import socket
import re

import time




def main():
    # tcp_server = init_server()
    #
    # # 循环去处理客户请求
    # run_server(tcp_server)

    # server = WebServer()
    # tcp_server = server.init_server()
    # WebServer.run_server(tcp_server)

    tcp_server = WebServer()
    tcp_server.run_server()




class WebServer(object):



    def run_server(self):
        """运行服务"""
        #客户端列表
        clients = list()



        #设置服务器端非堵塞
        self.tcp_server.setblocking(False)
        while True:
            try:
                client, addr = self.tcp_server.accept()

                # print(client)
                # print(addr)  F2定位错误
                # self.client_exec(client))
                #客户端也是非堵塞
                client.setblocking(False)

                #放到我们的列表中
                clients.append(client)
            except Exception as e:
                pass


            # else:
            # print("-------错误---------")
            #循环去遍历我们的列表
            for client_new in clients:
                # print("------xxxxxx------",clients)
                try:
                    data = client_new.recv(1024).decode()
                    print(data)
                    if data:
                        #有数据
                        self.client_exec(client_new,data)
                    else:
                        print("关闭了客户端")
                        #关闭了客户端
                        client_new.close()
                        clients.remove(client_new)

                except Exception as e:
                    pass




        # 关闭服务器
        self.tcp_server.close()

    def client_exec(self, client,data):
        """这个就是单独客户端的处理"""
        # 接收数据
        # data = client.recv(1024).decode()
        head_lines = data.splitlines()
        try:
            print(head_lines[0])
            # GET /index.html HTTP/1.1
            # 使用正则去获取地址
            re_match = re.match(r'[^/]+(/[^ ]*)', head_lines[0])
            # 判断是否匹配了
            if re_match:  # 匹配 了
                file_name = re_match.group(1)
                # 如果是/那么去首页
                if file_name == "/":
                    file_name = "/index.html"
        except Exception as e:
            print(e)  # 工作中是记录到文件

        # 返回数据
        # 响应头
        # 空行
        # 响应体
        try:
            headers = "HTTP/1.1 200 OK\r\n"

            # 会根据不同的地址返回不的内容
            # 打开文件写读文件内容
            with open("./html%s" % file_name, 'rb') as f:  # 这样写有一个好处,如果是图片就不会有问题
                body = f.read()  # 读取文件

            # body = "show page is find!"

            # content = headers +"\r\n" +body
            content = headers + "\r\n"

            # client.send(content.encode("utf-8"))
            client.send(content.encode("utf-8"))
            client.send(body)
        except Exception as e:
            print(e)
            # 返回一个404的正常显示的页面
            head = "HTTP/1.1 404 NOT FIND\r\n"
            body = "not find page!"
            content = head + "\r\n" + body

            client.send(content.encode("utf-8"))

        # 关闭客户端
        client.close()

    # alt+j列编辑
    def __init__(self):  # ctrl+B进入到函数
        """ 初始化tcp服务器"""
        # 服务器tcp服务器对象
        self.tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 设置我们的端口地址重用
        self.tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # 绑定端口号
        self.tcp_server.bind(("", 6789))
        # 改成被动模式
        self.tcp_server.listen(128)

    # return tcp_server


if __name__ == '__main__':
    main()


#二._tcp端服务器使用_epoll实现多任务处理

import socket

import select


def main():
    tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    tcp_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    tcp_server.bind(("",8989))
    tcp_server.listen(128)
    #创建epoll对象
    select_epoll = select.epoll()
    #注册
    select_epoll.register(tcp_server.fileno(),select.EPOLLIN)  #tcp_server.fileno这个是文件标识符 ,epollin这个就是数据 来
    #字典
    epoll_dict= dict()

    while True:
        # client,addres = tcp_server.accept()
        epoll_list = select_epoll.poll()  #这个epoll的列表有数据过来的时候
        #列表循环的判断
        for fd,evnet in epoll_list:
            if fd == tcp_server.fileno():
                #说明服务端的数据
                client,address = tcp_server.accept()  #直接接收数据
                #客户端的数据也要注册,因为我客户也要收数据
                #注册
                select_epoll.register(client.fileno(),select.EPOLLIN)
                #把每一个客户端存起来,方便后期访问
                epoll_dict[client.fileno()] = client
            else:
                #客户端的数据
                data = epoll_dict[fd].recv(1024).decode()
                #处理用户关闭的连接
                if data:
                    print(data)
                else:
                    epoll_dict[fd].close() #关闭连接
                    select_epoll.unregister(fd) #反注册,注销,从epoll删除
                    # epoll_dict.pop(fd)  #删除字典
                    del epoll_dict[fd] #删除字典

if __name__ == '__main__':
    main()






阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭