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

2019-09-28  本文已影响0人  jxvl假装
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)
上一篇下一篇

猜你喜欢

热点阅读