Python and UDP listening

python, udp

Solution

You are trying to bind the same port, twice.

You bind it once in the sender:

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

and again at the receiver

s.bind(('', port))

And since these are running on the same machine, you are getting an error.

Unless you care what the source port is, you don't need to `bind()` on the sender, just send it and the stack will pick an appropriate outgoing source port number. In the case of a sender, when you transmit a UDP datagram you specify the destination (`udpSocketSend->writeDatagram(...)`), and the `bind` actually determines the source of the outgoing datagram. If you don't `bind`, thats fine, the stack will assign you a port.

If you do care what the source port is, then I suggest you use a different port number for outgoing source port and incoming destination port. Then you would be able to bind both sender and receiver without issue.

Lastly, there is the option to set the `SO_REUSEADDR` socket option (in whatever language you're using). This would be necessary if you want to run multiple clients on the same machine, as all the clients would have to bind to the same address. But, I'm not sure whether this socket option is cross platform (*nix works fine) and I think the above suggestions are better.

Problem

I have an app, software defined radio, that broadcasts UDP packets on a port that tell listeners what frequency and demodulation mode have been set (among other things.) I've written a demo python client (code below) that listens to the port, and dumps out the information in the appropriate packets to the console. These are both running under OSX 10.6, Snow Leopard. They work there. The question/issue I have is: the Python app has to be started before the radio app or it claims the port is already in use (ERRNO 47) during bind, and I don't understand why. The radio app is broadcasting UDP; certainly I want to accommodate multiple listeners -- that's the idea of broadcasting, or at least, so I thought. So here's the Python code (the indent is a little messed up due to stack overflow's really dumb "make-it-code" indent, but I assure you it's ok): ``` #!/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's the Qt code that is sending the 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 } ```

Original source