简体   繁体   中英

Sharing multicast receiver ports between Python and Qt

I'm creating a Python 2.7 multicast listener like this:

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('', PORT))
groupAddress = 0
for byte in [224, 0, 0, 243]:
    groupAddress = (groupAddress << 8) | byte
packedGroupAddress = struct.pack('LL', socket.htonl(groupAddress), socket.htonl(socket.INADDR_ANY))
s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, packedGroupAddress)

In another application written in C++ with Qt 4.8, I create a multicast listener like this:

QUdpSocket socket;
if (not socket.bind(PORT, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint)) {
    qDebug() << "Binding failed:" << socket.error();
}
socket.joinMulticastGroup(QHostAddress("224.0.0.243"));

Both work fine, I can receive multicast packets like I intend to. What doesn't work is running both at the same time. If I first start the Python application, then Qt complains:

Binding failed: QAbstractSocket::AddressInUseError

If I run the Qt version first, then Python throws an exception with this (abbreviated) traceback:

Traceback (most recent call last):
  [...]
  File "/usr/local/lib/python2.7/dist-packages/gdcp/announcer.py", line 196, in _setupSocket
   s.bind(('', PORT))
  File "/usr/lib/python2.7/socket.py", line 224, in meth
   return getattr(self._sock,name)(*args)
socket.error: [Errno 98] Address already in use

I can run both versions multiple times in parallel without either showing this error, so the address sharing seems to work. Just when I mix Python and and Qt sockets, I get this behaviour. I'm running Ubuntu 14.04, although the above snippets are supposed to run on Windows as well. I couldn't test yet whether or not Windows shows the same problem.

So, anyone got a solution or at least an explanation why it doesn't work?

I am seeing a similar problem sharing multicast receiver ports using Qt 4.8.5 and Java 8 on Red Hat Enterprise Linux 6.5. I can run multiple Qt receiver clients or multiple Java receiver clients simultaneously. But if I run one type of client, the other type will not bind the socket.

I have a partial solution, which is to explicitly call setsockopt() to re-set the SO_REUSEADDR flag in the Qt application after joining the multicast group. That lets me start the Java client(s) after starting the Qt client(s). All clients are receiving properly, but I can't start any more Qt clients after starting the first Java client or the bind will fail. If I close all Java clients, I can then open more Qt clients. But as soon as the first Java client binds, no more Qt clients can bind. Very odd.

My Qt code now looks something like this:

if (_socket->bind(port, QUdpSocket::ShareAddress|QUdpSocket::ReuseAddressHint))
{
  if (_socket->joinMulticastGroup(bindAddr))
  {
    int reuse = 1;
    if (setsockopt(_socket->socketDescriptor(), SOL_SOCKET, SO_REUSEADDR,
                  (char *)&reuse, sizeof(reuse)) < 0)
      qDebug() << "setsockopt() failed";
  }
  else
    qDebug() << "joinMulticastGroup() failed";
}
else
  qDebug() << "bind() failed";

I don't have the source to the Java client, but I'm told it is using the java.net.MulticastSocket class in the recommended fashion.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM