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):

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)
    s.bind(('', port))
    print 'failure to bind'

# Listen for messages
looping = True

while looping:
    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

    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:


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


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
  • These two apps are running on the same machine, yes? – jedwards Jun 4 '12 at 20:28
  • You need to fix the indentation. After try: there cannot be a line that has the same indentation level as the try: statement. – ThiefMaster Jun 4 '12 at 20:35
  • @jedwards, yes. ThiefMaster: as I explicitly said right above the Python code, stackoverflow's formatting messed up the indent. The code is indented correctly. No worries there. – fyngyrz Jun 5 '12 at 0:53

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.

  • 1
    +1, but just to make it totally explicit, in TCP/IP communication, you almost never care what the source port is. Pretty much the only time you'd care is if you were trying to negotiate a particular set of firewall rules. – Russell Borogove Jun 4 '12 at 20:58
  • Russell: this is UDP. Not TCP. @jedwards: I need the (single) application to send a broadcast that can be received by multiple clients. I need for the clients -- possibly several of them -- to be able to send messages to the application. In no case do I want the user to actually have to set anything up. It seemed that the idea of broadcasting fit both ends (and nothing else really seemed to.) Am I wrong? – fyngyrz Jun 5 '12 at 0:23

Your Answer

