网络编程并发问题

网络编程并发问题

单进程设置为非阻塞

from socket import *

# 创建一个对象
tcp_server = socket(AF_INET, SOCK_STREAM)
# 设置对象为非阻塞
tcp_server.setblocking(False)
# 绑定地址和端口
tcp_server.bind(("", 6667))
# 设置监听的数量
tcp_server.listen(3)
socket_lists = []
while True:
    # 等待连接
    try:
        new_socket, address = tcp_server.accept()
        # 设置新socket为非阻塞
        new_socket.setblocking(False)
        socket_lists.append((new_socket, address))
    except:
        pass
    else:
        print(address)

    for sock, address in socket_lists:
        try:
            data = sock.recv(1024)
        except:
            pass
        else:
            if data:
                print(f"接收到{address}信息:  {data.decode('gb2312')}")
            else:
                # 关闭连接
                sock.close()
                socket_lists.remove((sock, address))

多进程并发服务器

from socket import *
from multiprocessing import Process


def rec_data(new_socket, address):
    while True:
        data = new_socket.recv(1024)
        if data:
            print(f"接收到{address}信息:  {data.decode('gb2312')}")
        else:
            # 关闭连接
            new_socket.close()


def main():
    # 创建一个对象
    tcp_server = socket(AF_INET, SOCK_STREAM)
    # 绑定地址和端口
    tcp_server.bind(("", 6667))
    # 设置监听的数量,超过3个就不再接收,此时的tcp_server只能够接听
    tcp_server.listen(3)
    while True:
        # 接收数据,获取新的socket,new_socket即可以接收也可以发送
        new_socket, address = tcp_server.accept()
        print(address)
        p = Process(target=rec_data, args=(new_socket, address))
        p.start()
        new_socket.close()


if __name__ == '__main__':
    main()

多线程并发服务器

from socket import *
from threading import Thread


def rec_data(new_socket, address):
    while True:
        data = new_socket.recv(1024)
        if data:
            print(f"接收到{address}信息:  {data.decode('gb2312')}")
        else:
            # 关闭连接
            new_socket.close()


def main():
    # 创建一个对象
    tcp_server = socket(AF_INET, SOCK_STREAM)
    # 绑定地址和端口
    tcp_server.bind(("", 6667))
    # 设置监听的数量,超过3个就不再接收,此时的tcp_server只能够接听
    tcp_server.listen(3)
    while True:
        # 接收数据,获取新的socket,new_socket即可以接收也可以发送
        new_socket, address = tcp_server.accept()
        p = Thread(target=rec_data, args=(new_socket, address))
        p.start()
        print(address)
        # new_socket.close()


if __name__ == '__main__':
    main()

IO多路复用(轮询方式)

import select
from socket import *


def main():
    # 创建一个对象
    tcp_server = socket(AF_INET, SOCK_STREAM)
    tcp_server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    # 绑定地址和端口
    tcp_server.bind(("", 6667))
    # 设置监听的数量,超过3个就不再接收,此时的tcp_server只能够接听
    tcp_server.listen(3)

    sock_lists = [tcp_server]
    while True:
        socket_lists, _, _ = select.select(sock_lists, [], [])
        for sock in socket_lists:
            if sock == tcp_server:
                new_socket, address = tcp_server.accept()
                print(address)
                sock_lists.append(new_socket)
            else:
                data = sock.recv(1024)
                if data:
                    print(f"接收到{data.decode('gb2312')}")
                else:
                    sock.close()
                    sock_lists.remove(sock)


if __name__ == '__main__':
    main()

epoll多路复用(事件通知机制)

from socket import *
import select


def main():
    # 创建对象
    tcp_server = socket(AF_INET, SOCK_STREAM)
    tcp_server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    # 绑定ip和端口
    tcp_server.bind(("", 2223))
    # 设置监听
    tcp_server.listen(5)

    epoll = select.epoll()
    epoll.register(tcp_server.fileno(), select.EPOLLIN)
    clients = {}
    while True:
        epoll_list = epoll.poll()
        for fd, events in epoll_list:
            print(fd, events)
            if fd == tcp_server.fileno():
                new_socket, address = tcp_server.accept()
                print(address)
                epoll.register(new_socket.fileno(), select.EPOLLIN)
                # 将新生成的socket对象存储到字典中
                clients[new_socket.fileno()] = new_socket
            else:
                data = clients[fd].recv(1024)
                if data:
                    print(f"接收到{data.decode('gb2312')}")
                else:
                    clients[fd].close()
                    # 注销文件符
                    epoll.unregister(fd)
                    # 删除socket对象
                    del clients[fd]

                    
if __name__ == '__main__':
    main()

select和epoll的区别

select: 有连接限制 32位系统 : 1024个, 64位系统:2048个. 采用轮询机制

epoll: 没有连接限制,采用事件通知机制

猜你喜欢

转载自blog.csdn.net/weixin_43958804/article/details/85145102