title: Python and UDP listening
body: <p>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.)</p>
  
  <p>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.</p>
  
  <p>These are both running under OSX 10.6, Snow Leopard. They work there.</p>
  
  <p>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.</p>
  
  <p>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):</p>
  
  <pre><code>#!/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 + "--&gt;" + 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'
  </code></pre>
  
  <p>For reference, here's the Qt code that is sending the UDP message:</p>
  
  <p>Setup:</p>
  
  <pre><code>bcast = new QHostAddress("192.168.1.255");
  if (bcast)
  {
      udpSocketSend = new QUdpSocket(0);
      if (udpSocketSend)
      {
          udpSocketSend-&gt;bind(*bcast, txudp);
      }
  }
  </code></pre>
  
  <p>Broadcast:</p>
  
  <pre><code>if (udpSocketSend)
  {
      QByteArray *datagram = new QByteArray(1024,0);  // datagram is full of zeroes
      strcpy(datagram-&gt;data(),msg);                   // except where text message is in it at beginning
      udpSocketSend-&gt;writeDatagram(*datagram, QHostAddress::Broadcast,txudp); // send
  }
  </code></pre>