Когда сокеты запускают событие для чтения - PullRequest
0 голосов
/ 23 марта 2020

Я изучаю сокеты со следующим python кодом для сервера:

import selectors
import socket
import types

host = "127.0.0.1"
port = 65432

def accept_wrapper(sock):
    conn, addr = sock.accept()
    print('accepted conneciton from', addr)
    conn.setblocking(False)
    data = types.SimpleNamespace(addr=addr, inb=b'', outb=b'')
    events = selectors.EVENT_READ | selectors.EVENT_WRITE
    sel.register(conn, events, data=data)

def service_connection(key, mask):
    sock = key.fileobj
    data = key.data
    if mask & selectors.EVENT_READ:
        recv_data = sock.recv(1024)
        if recv_data:
            data.outb += recv_data
        else:
            print('closing connection to', data.addr)
            sel.unregister(sock)
            sock.close()
    if mask & selectors.EVENT_WRITE:
        if data.outb:
            print('echoing', repr(data.outb), 'to', data.addr)
            sent = sock.send(data.outb)
            data.outb = data.outb[sent:]

sel = selectors.DefaultSelector()
lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
lsock.bind((host, port))
lsock.listen()
print('listening on', (host, port))
lsock.setblocking(False)
sel.register(lsock, selectors.EVENT_READ, data=None)

while True:
    events = sel.select(timeout=None)
    for key, mask in events:
        if key.data is None:
            # From the listening socket
            accept_wrapper(key.fileobj)
        else:
            # Client Socket
            service_connection(key, mask)

и следующим для клиента

import socket
import selectors
import types

host = "127.0.0.1"
port = 65432
numm_conns = 2
messages = [b'Message 1 from client', b'Message 2 from client']

def start_connections(host, port, num_conns):
    server_addr = (host, port)
    for i in range(0, num_conns):
        connid = i + 1
        print('starting connection', connid, 'to', server_addr)
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.setblocking(False)
        sock.connect_ex(server_addr)
        events = selectors.EVENT_READ | selectors.EVENT_WRITE
        data = types.SimpleNamespace(
            connid = connid,
            msg_total=sum(len(m) for m in messages),
            recv_total = 0,
            messages=list(messages),
            outb=b''
        )
        sel.register(sock, events, data=data)

def service_connection(key, mask):
    sock = key.fileobj
    data = key.data
    if mask & selectors.EVENT_READ:
        recv_data = sock.recv(1024)
        if recv_data:
            print('received', repr(recv_data), 'from connection', data.connid)
            data.recv_total += len(recv_data)
        if not recv_data or data.recv_total == data.msg_total:
            print('closing connection', data.connid)
            sel.unregister(sock)
            sock.close()
    if mask & selectors.EVENT_WRITE:
        if not data.outb and data.messages:
            data.outb = data.messages.pop(0)
        if data.outb:
            print('sending', repr(data.outb), 'to connection', data.connid)
            sent = sock.send(data.outb)
            data.outb = data.outb[sent:]

sel = selectors.DefaultSelector()
start_connections(host, port, numm_conns)

while True:
    events = sel.select(timeout=None)
    print()
    print(events)
    print()
    for key, mask in events:
        service_connection(key, mask)

На клиенте первое событие, которое срабатывает в случае, если l oop для обоих сокетов равно 2, что означает, что сокеты готовы к записи. Мой вопрос: почему не было события 3? Разве они не должны быть доступны для чтения? Или это событие срабатывает только тогда, когда что-то было недавно записано в сокет?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...