问题
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
回答1:
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.
来源:https://stackoverflow.com/questions/60728011/how-to-make-send-call-asynchronous