美文网首页
Python56_TCP:单进程、线程、非阻塞实现为多个客户服务

Python56_TCP:单进程、线程、非阻塞实现为多个客户服务

作者: jxvl假装 | 来源:发表于2019-09-28 10:58 被阅读0次
    from socket import *
    import time
    
    tcp_server = socket(AF_INET, SOCK_STREAM)
    tcp_server.bind(("", 9999))
    tcp_server.listen(128)
    tcp_server.setblocking(False)  # 设置为非阻塞
    client_socket_list = []
    while True:
        time.sleep(0.5)  # 为了验证程序,使程序的速度慢一点
        try:
            new_socket, new_addr = tcp_server.accept()  # 因为设置了非阻塞,
        # 如果这里没有新的客户端到来,就不会阻塞,但是会以异常的方式提示
        except:
            print("没有新的客户端到来")
        else:  # 如果没有异常,表示有新的客户端到来
            print("没有产生异常,即表明来了一个新的客户端")
            new_socket.setblocking(False)  # 将new_socket也设置为非阻塞
            client_socket_list.append(new_socket)
        for client in client_socket_list:
            try:
                recv_data = client.recv(1024).decode("utf-8")  # 因为设置了非阻塞,
            # 所以如果这里客户端没有发送过来数据,就不会阻塞,而是会以异常的方式提示
            # 如果recv没有产生异常而且没有数据返回,就表明这个客户端的链接已经断开
                print(recv_data)
            except:
                print("这个客户端没有发送过来数据")
            else:
                if recv_data:
                    print("这个客户端发送过来了数据")
                else:
                    # 对方调用了close导致recv返回
                    client.close()
                    client_socket_list.remove(client)
                    print("客户端已经关闭")
    
    

    可以配合网络调试助手进行验证

    以上程序实际上为短连接,那么如何实现长连接呢?

    from socket import *
    import time
    import re
    
    
    def service_client(new_socket, request):
        # request = new_socket.recv(1024).decode("utf-8")
        request_lines = request.splitlines()
    
        for line in request_lines:
            print(line)
    
        file_name = None
        ret = re.search(r"/\w*", request_lines[0])
        print(ret.group())  # 测试用,输出匹配到的内容
        if ret:
            file_name = ret.group()
            if file_name == "/":
                file_name = "/index.html"
    
        try:
            f = open("." + file_name, "rb")
        except:
            response = "HTTP/1.1 404 NOT FOUND\r\n\r\n"
            new_socket.send(response.encode("utf-8"))
        else:
            html_content = f.read()
            f.close()
    
            response_body = html_content
            response_header = "HTTP/1.1 200 OK\r\nContent-Length:{}\r\n\r\n".format(len(response_body)) # header中添加Content_Length,让浏览器知道本只传输内容的长度
            response = response_header.encode("utf-8") + response_body
    
            new_socket.send(response)
            # new_socket.close()    # 如果此处有关闭,就又变成了短连接,
            # 但是如果不close,浏览器就不知道请求的数据传送完了没有,就一直“转圈”
            # 如何让浏览器知道本次传输已经完成?在header里面添加"Content-Length:%d"%(本次传输内容(body)的字节数)
    
    
    def main():
        tcp_server = socket(AF_INET, SOCK_STREAM)
        tcp_server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        tcp_server.bind(("", 9999))
        tcp_server.listen(128)
        tcp_server.setblocking(False)  # 设置为非阻塞
        client_socket_list = []
        while True:
            # time.sleep(0.5)  # 为了验证程序,使程序的速度慢一点
            try:
                new_socket, new_addr = tcp_server.accept()
            except:
                pass
            else:  # 如果没有异常,表示有新的客户端到来
                new_socket.setblocking(False)
                client_socket_list.append(new_socket)
    
            for client_socket in client_socket_list:
                try:
                    recv_data = client_socket.recv(1024).decode("utf-8")
                except:
                    pass
                else:
                    if recv_data:
                        service_client(client_socket, recv_data)
                    else:
                        client_socket_list.remove(client_socket)
    

    相关文章

      网友评论

          本文标题:Python56_TCP:单进程、线程、非阻塞实现为多个客户服务

          本文链接:https://www.haomeiwen.com/subject/itkuuctx.html