Как сделать вызов send () асинхронным? - PullRequest
2 голосов
/ 17 марта 2020

Сервер работает как nc -l 1234


Ниже представлен клиент, который не заблокирован на recv() с использованием события l oop s select() call.

client.py

import socket
import sys
from eventloop import EventLoop

class Connection():
    def __init__(self):
        self.sock = socket.socket()
        self.sock.connect(('localhost', 1234))

    def fileno(self):
        return self.sock.fileno()

    def onRead(self):
        msg = self.sock.recv(1000).decode('utf-8')
        print(msg)

    def send(self, msg):
        self.sock.send(msg)

class Input():
    def __init__(self, sock):
        self.sock = sock

    def fileno(self):
        return sys.stdin.fileno()

    def onRead(self):
        msg = sys.stdin.readline().encode('utf-8')
        self.sock.send(msg)

sock = Connection()
inputReader = Input(sock)

eventLoop = EventLoop()
eventLoop.addReader(sock)
eventLoop.addReader(inputReader)
eventLoop.runForever()

eventl oop .py

import select

class EventLoop():
    def __init__(self):
        self.readers = []

    def addReader(self, reader):
        self.readers.append(reader)

    def runForever(self):
        while True:
            readers, _, _ = select.select(self.readers, [], [])
            for reader in readers:
                reader.onRead()

Но self.sock.send(msg) вызов может быть заблокирован по разным причинам:

1) сбой сервера

2) Удаленный сервер (не localhost) недоступен из-за обрыва сетевого кабеля


Как сделать send() звонок не заблокированным? просто бросив сообщение и продолжив остальные функции ... без использования asyncio

1 Ответ

2 голосов
/ 17 марта 2020

Как сделать так, чтобы вызов send () не блокировался?

С помощью неблокирующего сокета, т.е. self.sock.setblocking(0). Имейте в виду, что отправка может произойти сбой, и вы должны поймать это. Отправка может также не отправлять все данные, но это также верно для блокирующих сокетов, и вы просто проигнорировали эту проблему.

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

...