Python asyncore with UDP
Asked Answered
P

3

2

Can I write an UDP client/server application in asyncore? I have already written one using TCP. My desire is to integrate it with support for UDP.

My question was not previously asked/answered by the following: Python asyncore UDP server

Prudish answered 2/12, 2015 at 10:40 Comment(0)
G
1

Yes you can. Here is a simple example:

class AsyncoreSocketUDP(asyncore.dispatcher):

  def __init__(self, port=0):
    asyncore.dispatcher.__init__(self)
    self.create_socket(socket.AF_INET, socket.SOCK_DGRAM)
    self.bind(('', port))

  # This is called every time there is something to read
  def handle_read(self):
    data, addr = self.recvfrom(2048)
    # ... do something here, eg self.sendto(data, (addr, port))

  def writable(self): 
    return False # don't want write notifies

That should be enough to get you started. Have a look inside the asyncore module for more ideas.

Minor note: asyncore.dispatcher sets the socket as non blocking. If you want to write a lot of data quickly to the socket without causing errors you'll have to do some application-dependent buffering ala asyncore.dispatcher_with_send.

Thanks to the (slightly inaccurate) code here for getting me started: https://www.panda3d.org/forums/viewtopic.php?t=9364

Guard answered 4/8, 2016 at 5:57 Comment(1)
Thanks for the self.sendto(data, (addr, port))Scarlet
P
1

After long search the answer is no. Asyncore assumes the underlying socket is connection-oriented, i.e. TCP.

Prudish answered 22/1, 2016 at 18:6 Comment(0)
G
1

Yes you can. Here is a simple example:

class AsyncoreSocketUDP(asyncore.dispatcher):

  def __init__(self, port=0):
    asyncore.dispatcher.__init__(self)
    self.create_socket(socket.AF_INET, socket.SOCK_DGRAM)
    self.bind(('', port))

  # This is called every time there is something to read
  def handle_read(self):
    data, addr = self.recvfrom(2048)
    # ... do something here, eg self.sendto(data, (addr, port))

  def writable(self): 
    return False # don't want write notifies

That should be enough to get you started. Have a look inside the asyncore module for more ideas.

Minor note: asyncore.dispatcher sets the socket as non blocking. If you want to write a lot of data quickly to the socket without causing errors you'll have to do some application-dependent buffering ala asyncore.dispatcher_with_send.

Thanks to the (slightly inaccurate) code here for getting me started: https://www.panda3d.org/forums/viewtopic.php?t=9364

Guard answered 4/8, 2016 at 5:57 Comment(1)
Thanks for the self.sendto(data, (addr, port))Scarlet
R
1

Hi thanks @bw1024 for pointing in the right direction, I will add my solution inspired by yours , pandas and the python asyncore documentation.

My use case is capturing some JSON from a UDP stream

`

import socket import json import asyncore

UDP_IP = '127.0.0.1' UDP_PORT = 2000

class AsyncUDPClient(asyncore.dispatcher): def init(self, host, port): asyncore.dispatcher.init(self) self.create_socket(socket.AF_INET, socket.SOCK_DGRAM) self.bind((host, port)) print("connecting.. host = '{0}'' port = '{1}'" .format(host, str(port)))

def handle_connect(self):
    print("connected")


def handle_read(self):
    data = self.recv(1024)
    y = json.loads(data)
    print("PM 2.5 ug/m^3 async : %s "% y['PM25MassPerM3'])

def writable(self):
    return False;

client = AsyncUDPClient(UDP_IP, UDP_PORT)

asyncore.loop()

`

P.S not sure why the code is not correctly being formatted its running on python 3.6.9 OK here is a link to a gist

Rigorism answered 20/4, 2021 at 16:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.