Python3 Socket / Selector регистрирует более одного события

Я всегда использовал блокирующие / синхронные сокеты, так как я понял, что неблокирующие / асинхронные сокеты могут быть более мощными, когда вы выполняете ввод-вывод.

Итак, для начала я решил сделать простой проект, создающий неблокирующий сокет, способный читать и записывать, когда события установлены, поэтому я в основном регистрирую события в селекторе, а затем вхожу в бесконечный цикл, ожидая события, когда события установлены, я перезваниваю их.

import socket
import selectors

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setblocking(False)
selector = selectors.DefaultSelector()

def write():
    print('Able to Write')
    sock.send(b'Hello')
    #I don't want to keep sending data, so I don't re-register the event

def read():
    print('Able to Read')
    data = sock.recv(1024).decode()
    selector.register(sock.fileno(), selectors.EVENT_READ, read) 
    # I register the event again because I'd like to keep reading from the socket.

# I don't use events here...
try:
    sock.connect(('localhost', 80))
except BlockingIOError:
    pass

# I register read and write events with their respective callbacks. Error is raised...
selector.register(sock.fileno(), selectors.EVENT_READ, read)
selector.register(sock.fileno(), selectors.EVENT_WRITE, write)

while True:
    events = selector.select()
    for key, _ in events:
        callback = key.data
        callback()
        selector.unregister(key.fileobj)
        #Unregister the event

Вот мой код
Моя цель - иметь возможность читать и писать асинхронно, поэтому я хочу зарегистрировать множество событий чтения и записи в одном сокете.

1 ответ

Вы должны зарегистрировать все события одновременно.

selector.register(sock.fileno(), selectors.EVENT_WRITE | selectors.EVENT_READ, write)

Это использует побитовое ИЛИ. Обратите внимание, что вы столкнетесь с той же проблемой в read(), так как вы не отменили регистрацию FD перед вызовом обратного вызова.

Другие вопросы по тегам