Mohammad M
Mohammad M

Reputation: 131

Receive data only if available in Python sockets

I want to receive data only if it is available. like Serial.available() in Arduino. I want code like this:

if there is data:
     receive and print
else:
     print 'No data'

In fact, I do not want the program to stop just for receiving data.

Upvotes: 6

Views: 7909

Answers (1)

Mark Tolonen
Mark Tolonen

Reputation: 178379

You can call .setblocking(False) on a socket to disable blocking mode. The call will raise a BlockingIOError when it would otherwise block. But then you have to handle exceptions when you .accept() or .recv() on the socket and there is no connection ready or no data to receive.

For example:

try:
    data = s.recv(1024)
    print(data)
except BlockingIOError:
    print('no data')

select.select can be used to poll multiple sockets for data. Here's a quick example:

import socket
import select

server = socket.socket()
server.bind(('', 8000))
server.listen()
readables = [server] # list of readable sockets.  server is readable if a client is waiting.
i = 0
while True:
    # to_read will be a list of sockets with readable data
    to_read, to_write, errors = select.select(readables, [], [], 0)
    for sock in to_read: # iterate through readable sockets
        if sock is server: # is it the server?
            client, address = server.accept()
            print(f'\r{address}: connected')
            readables.append(client) # add the client
        else:
            # read from address client
            data = sock.recv(1024)
            if not data:
                print(f'\r{sock.getpeername()}: disconnected')
                readables.remove(sock)
                sock.close()
            else:
                print(f'\r{sock.getpeername()}: {data}')
    # a simple spinner to show activity
    i += 1
    print(r'/-\|'[i%4], end='\r', flush=True)

Example where two clients connected, sent something and disconnected:

('127.0.0.1', 2983): connected
('127.0.0.1', 2983): b'hello'
('127.0.0.1', 2985): connected
('127.0.0.1', 2985): b'there'
('127.0.0.1', 2983): disconnected
('127.0.0.1', 2985): disconnected
<spinner activity here>

Upvotes: 8

Related Questions