MsSkillz007
MsSkillz007

Reputation: 45

How can i receive packets asynchronously using asyncio

I am trying to receive data asynchronously using asyncio sock_recv. I am sending data from a server to two different ports with different speeds : data X every 10ms and data Y every 100ms.

When using blocking socket recvfrom function i'd receive X and Y every 100ms since it blocks in the Y recvfrom, so i tried using asyncio so that while Y is waiting i would receive 10 X and then one Y.

To do that i wrote those functions :

async def recv_data(socket):
      data = await loop.sock_recv(socket, 2048)

      print(len(data))

async def main():

    UDP_IP = "192.168.1.10"
    RAW_PORT = 125
    MCU_PORT = 126 
    SERVER_PORT = 5001

    SOCK_RAW = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    SOCK_RAW.bind(('', RAW_PORT))

    SOCK_MCU = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    SOCK_MCU.bind(('', MCU_PORT))

    while True :       

        await asyncio.gather(recv_data(SOCK_RAW), recv_data(SOCK_MCU))


while True:

   loop = asyncio.get_event_loop()
   loop.run_until_complete(main())

But what i get with this is not quite what i expect :

576
540
576
540
576
540
540
576
540
576
576
540
576
540
576
540
540
576
540
576

Am i not using the asyncio package in a good way ?

Upvotes: 1

Views: 1748

Answers (1)

IVI
IVI

Reputation: 149


import asyncio
import socket

async def recv_data(c_socket):
    while True : # also add an interuption logic as break the loop if empty string or what you have there
        data = await loop.sock_recv(c_socket, 2048)
        if data == '':
          break
        print(len(data))

def create_socket(port, host='localhost'):
    server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    server.bind(('', port))
    server.setblocking(False)
    return server


async def main():
    UDP_IP = "192.168.1.10"
    RAW_PORT = 125
    MCU_PORT = 126
    SERVER_PORT = 5001

    servers = [
        create_socket(port) for port in { RAW_PORT, MCU_PORT }
    ]

    listen_connections = [ 
        loop.create_task( recv_data(server) ) for server in servers 
    ]
    await asyncio.gather(*listen_connections)


loop = asyncio.get_event_loop()
loop.run_until_complete(main())

The problem was in your while loop recv_data is receiving data only once and waits when it will be called one more time, and a job at 100ms socket is not finished means while loop still stays at the same iteration with a waiting time of 100ms.

I edited the code a bit, I mist watch sockets was not set to nonblocking mode thats why you getting an only response from one socket

Upvotes: 1

Related Questions