2

Server is running as nc -l 1234


Below is the client that is not blocked on recv() using event loop'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()

eventloop.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()

But self.sock.send(msg) call can get blocked for different reasons:

1) server is crashed

2) Remote server(not localhost) is not reachable, due to broken network cable


How to make send() call not blocked? by just throwing the message and continue with rest of the functionality... without using asyncio

overexchange
  • 15,768
  • 30
  • 152
  • 347

1 Answers1

2

How to make send() call not blocked?

By using a non-blocking socket, i.e. self.sock.setblocking(0). Be aware though that a send might fail then and you have to catch this. A send might also not send all given data, but this is also true with blocking sockets and you just ignored this problem.

Given that you currently have no problems with your blocking connect you should set the socket to non-blocking only after the blocking connect. Or you have to deal with implementing a non-blocking connect which is a bit more tricky.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • Do I need to set this in both `Connection` & `Input` class? – overexchange Mar 17 '20 at 18:27
  • @overexchange: You need to set this exactly once on the socket, i.e. either in Connection or in Input but not both. Probably in Connection after the `connect`. – Steffen Ullrich Mar 17 '20 at 18:28
  • Does this affect `recv()` blocking call? which is not blocked currently due to `select()` – overexchange Mar 17 '20 at 18:30
  • @overexchange: Yes, every operation on the socket will not block but instead result in an error if it would block. – Steffen Ullrich Mar 17 '20 at 18:32
  • But how asynchronous `send()` different from `send()` using socket that has `self.sock.setblocking(0)`? – overexchange Mar 17 '20 at 18:48
  • @overexchange: What exactly do you mean with *"asynchronous send()"*. Asynchronous to what? Usually this means internally that the writing will be attempted and if it fails it will be retried later (when socket is ready) and in the mean time it will execute some other stuff, i.e. writing is done asynchronous to the other stuff. – Steffen Ullrich Mar 17 '20 at 18:56
  • Asynchronous to both(*underlying communication channel* and *receiver*) – overexchange Mar 17 '20 at 19:02
  • @overexchange: I have no idea what you mean with that. A `send` will only wait until the data are put into the local socket buffer anyway. It will not wait until the data are transmitted to the receiver and maybe even processed there. – Steffen Ullrich Mar 17 '20 at 19:12
  • Does `self.sock.setblocking(0)` help us not block from local socket buffer issues(if any)? Yes.. I was assuming wrongly that `send()` was a blocking call until receiver receives it.. thanks for correcting me – overexchange Mar 17 '20 at 19:16
  • 1
    @overexchange: Setting a socket non-blocking causes it to fail when putting data into a full socket buffer instead of blocking until there is space in the socket buffer. – Steffen Ullrich Mar 17 '20 at 19:23