Python and UDP playback

I have an application defined by software that sends UDP packets to a port that tell listeners what frequency and demodulation mode are set (among other things).

I wrote a demo python client (code below) that listens on the port and uploads information to the appropriate packages on the console.

They work under OSX 10.6, Snow Leopard. They work there.

I have a question / question: the Python application must be running before the radio application or it claims that the port is already in use (ERRNO 47) during the binding, and I do not understand why. The radio application broadcasts UDP; Of course, I want to accommodate a few listeners - which is the idea of ​​broadcasting, or at least that's what I thought.

So, here is the Python code (the indentation is a bit confused due to the really stupid indentation of “make-it-code”, but I assure you):

#!/usr/bin/python import select, socket # AA7AS - for SdrDx UDP broadcast # this is a sample python script that captures the UDP messages # that are coming from SdrDx. SdrDx tells you what frequency and # mode it has been set to. This, in turn, would be used to tell # another radio to tune to that frequency and mode. # UDP packet from SdrDx is zero terminated, but receiving the # packet makes it seem like the string contains zeros all the # way out to the 1024th character. This function extracts a # python string up to the point where it hits the first zero, # then returns that string. # ----------------------------------------------------------- def zeroterm(msg): counter = 0; for c in msg: if ord(c) != 0: counter += 1 strn = msg[:counter] return strn port = 58083 # port where we expect to get a msg bufferSize = 1024 # room for message # Create port to listen upon # -------------------------- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: s.bind(('', port)) except: print 'failure to bind' s.close() raise s.setblocking(0) # Listen for messages # ------------------- looping = True while looping: try: result = select.select([s],[],[]) except: # you can kill the client here with control-c in its shell s.close() # must close socket print 'Closing, exception encountered during select' # warn raise SystemExit # and quit msg = result[0][0].recv(bufferSize) # actually fetch the UDP data msg = zeroterm(msg) # convert content into python string # in next line, [] contain optional repeats # message format is keyword:data[|keyword:data] # where from 1...n keyword:data pairs may appear, up to 1024 bytes # ---------------------------------------------------------------- try: msgs = msg.split('|') # can be more than one message in packet except: # failed to split msgs = [] # on the other hand, can just be one. :) msgs.append(msg) # so build array with that one. for m in msgs: # now, for every message we have keyw,data = m.split(':') # break into keyword and data print keyw + "-->" + data # you'd do something with this if keyw == "closing": # Our client terminates when SdrDx does looping = False # loop stops s.close() # must close socket print 'Normal termination' 

For reference, here is a Qt code that sends a UDP message:

Setup:

 bcast = new QHostAddress("192.168.1.255"); if (bcast) { udpSocketSend = new QUdpSocket(0); if (udpSocketSend) { udpSocketSend->bind(*bcast, txudp); } } 

Broadcast:

 if (udpSocketSend) { QByteArray *datagram = new QByteArray(1024,0); // datagram is full of zeroes strcpy(datagram->data(),msg); // except where text message is in it at beginning udpSocketSend->writeDatagram(*datagram, QHostAddress::Broadcast,txudp); // send } 
+7
source share
1 answer

You are trying to bind the same port twice.

You bind it once in the sender:

 if (udpSocketSend) { udpSocketSend->bind(*bcast, txudp); } 

and again in the receiver

 s.bind(('', port)) 

And since they work on the same computer, you get an error message.

If you do not need the source port, you do not need the bind() sender, just send it and the stack will select the appropriate port number of the outgoing source. In the case of the sender, when you pass the UDP datagram, you specify the destination ( udpSocketSend->writeDatagram(...) ), and bind actually determines the source of the outgoing datagram. If you are not bind , this is normal, the stack will assign you a port.

If you don't care what the source port is, I suggest you use a different port number for the outgoing source port and the incoming destination port. Then you can easily associate both the sender and the recipient.

Finally, it is possible to set the SO_REUSEADDR socket SO_REUSEADDR (in any language that you use). This is necessary if you want to run several clients on the same computer, since all clients will need to bind to the same address. But I'm not sure if this socket option is cross-platform (* nix works fine), and I think the suggestions above are better.

+6
source

All Articles