Asyncore UDP Networking Made Easy!

Here is a simple example of UDP networking with asyncore.

Details:

  • UDP is connectionless and “unreliable” meaning you should use sendto( “msg”, (“ip”,port)) and hope the packet arrives at the destination.
  • UDP is a good choice when speed is more important than accuracy, UPD is common for first person shooter games.
  • Asyncore is used to stop the networking from blocking your program. Call asyncore.loop() to send/receive some packets.
  • Use asyncore.loop(count=5) or asyncore.loop(timeout=0) to tune the amount of time spent sending/receiving packets.

Client:

import socket, asyncore

class AsyncoreClientUDP(asyncore.dispatcher):

	def __init__(self, server, port):
		self.server = server
		self.port = port
		self.buffer = ""

		# Network Connection Magic!
		asyncore.dispatcher.__init__(self)
		self.create_socket(socket.AF_INET, socket.SOCK_DGRAM)
		self.bind( ('', 0) ) # bind to all interfaces and a "random" free port.
		print "Connecting..."

	# Once a "connection" is made do this stuff.
	def handle_connect(self):
		print "Connected"
	
	# If a "connection" is closed do this stuff.
	def handle_close(self):
		self.close()

	# If a message has arrived, process it.
	def handle_read(self):
		data, addr = self.recv(2048)
		print data

	# Actually sends the message if there was something in the buffer.
	def handle_write(self):
		if self.buffer != "":
			print self.buffer
			sent = self.sendto(self.buffer, (self.server, self.port))
			self.buffer = self.buffer[sent:]

connection = AsyncoreClientUDP("127.0.0.1",5005) # create the "connection"
while 1:
	asyncore.loop(count = 10) # Check for upto 10 packets this call?
	connection.buffer += raw_input(" Chat > ") # raw_input (this is a blocking call)

Server:

import asyncore, socket

class AsyncoreServerUDP(asyncore.dispatcher):
	def __init__(self):
		asyncore.dispatcher.__init__(self)

		# Bind to port 5005 on all interfaces
		self.create_socket(socket.AF_INET, socket.SOCK_DGRAM)
		self.bind(('', 5005))

	# Even though UDP is connectionless this is called when it binds to a port
	def handle_connect(self):
		print "Server Started..."

	# This is called everytime there is something to read
	def handle_read(self):
		data, addr = self.recvfrom(2048)
		print str(addr)+" >> "+data

	# This is called all the time and causes errors if you leave it out.
	def handle_write(self):
		pass

AsyncoreServerUDP()
asyncore.loop()

Notes:

  • This simple server only receives packets and prints them, it does not respond to the client or keep track of the client IPs or Ports
  • The client does block when it gets to the raw_input() call.
  • If you are going to use this code packed into a p3d file you need to use the “-r morepy” flag

I hope someone finds this useful, let me know if you have any questions or if I made any mistakes.

Thanks,
Daniel.

Hey,

Looks like a promising example, thanks for contributing it to our community :slight_smile:.

William v. Doorn

Hi,

Your example seems to be perfect fit for my application.
I am trying to render a virtual hand in p3d that received joint angles via udp from another program MATLAB SIMULINK.

Receiver: p3d program
Sender: MATLAB SIMULINK

I am new to p3d too.
Can you please help me how to use your code to work for this application

Thank you very much.

.

Thanks for pointing that out atari314, I have corrected the above example.