python3 网络IO 阻塞IO 非阻塞IO

111 阅读1分钟

阻塞IO

'''
网络IO

阻塞io

非阻塞io

多路复用io

异步io

'''
import time
from threading import Thread0

import socket


def server():
    server = socket.socket()
    server.bind(("127.0.0.1", 8080))
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    server.listen(4)
    while True:
        conn, (ip, addr) = server.accept()
        while True:
            data = conn.recv(1024)
            if len(data) == 0: break
            conn.send(data.upper())
        conn.close()


def client():
    client = socket.socket()
    client.connect(("127.0.0.1", 8080))
    count = 0
    while True:
        data = "Hello world"
        b_data = data.encode("utf-8")
        count += len(b_data)
        print("count is ", count)
        client.send(b_data)
        data = client.recv(1024)
        print(data.decode("utf-8"))


if __name__ == '__main__':
    Thread(target=server).start()
    Thread(target=client).start()

非阻塞IO

非阻塞IO由于一直循环,因此如果没有数据连接也会导致占用非常高的CPU。


import time
from threading import Thread0

import socket


def server():
    server = socket.socket()
    server.bind(("127.0.0.1", 8080))
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    server.listen(4)

    # 设置为非阻塞,默认为True
    server.setblocking(False)

    while True:
        try:
            conn, (ip, addr) = server.accept()
        except BlockingIOError as e:
            print(e)
        while True:
            data = conn.recv(1024)
            if len(data) == 0: break
            conn.send(data.upper())
        conn.close()


def client():
    client = socket.socket()
    client.connect(("127.0.0.1", 8080))
    count = 0
    while True:
        data = "Hello world"
        b_data = data.encode("utf-8")
        count += len(b_data)
        print("count is ", count)
        client.send(b_data)
        data = client.recv(1024)
        print(data.decode("utf-8"))


if __name__ == '__main__':
    Thread(target=server).start()
    Thread(target=client).start()

多路复用

select windows和linux都有

poll机制 只有Linux有, poll和select都可以监听多个对象,但是poll监管的数量更多。

epoll机制。只有Linux有。 每个监听对象都绑定一个回调机制。


selectors模块,可以根据不同的平台自动选择不同的实现
import select
import socket

server = socket.socket()
server.bind(("127.0.0.1", 8080))
server.setblocking(False)
server.listen(5)

read_list = [server]

while True:
    # 如果server有新的连接,conn有新的消息,都会返回到第一个
    # 写数据的时候,如果对方收的比较慢,则缓存区会满,此时也会阻塞。
    read,write,e = select.select(read_list, [], []) # 监听server

    for i in read:
        if i is server:
            conn, (ip, addr) = i.accept()
            read_list.append(conn)
        else:
            data = i.recv(1024)
            if len(data) == 0:
                i.close()
                read_list.remove(i)
                continue
            i.send(data.upper())

异步IO

异步IO

模块: asyncio模块
框架: sanic tronado twisted