在Python和Qt之间共享多播接收器端口

时间:2014-08-21 11:10:17

标签: python c++ qt udp multicast

我正在创建这样的Python 2.7多播侦听器:

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)

在使用Qt 4.8用C ++编写的另一个应用程序中,我创建了一个这样的多播侦听器:

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

两者都工作正常,我可以像我打算那样接收多播数据包。什么不起作用是同时运行。如果我第一次启动Python应用程序,那么Qt会抱怨:

Binding failed: QAbstractSocket::AddressInUseError

如果我先运行Qt版本,那么Python会抛出这个(缩写)回溯的异常:

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

我可以多次并行运行这两个版本而不显示此错误,因此地址共享似乎有效。就在我混合Python和Qt套接字时,我得到了这种行为。我正在运行Ubuntu 14.04,尽管上面的代码段也应该在Windows上运行。我无法测试Windows是否显示同样的问题。

所以,任何人都有解决方案或至少解释为什么它不起作用?

1 个答案:

答案 0 :(得分:0)

我看到在Red Hat Enterprise Linux 6.5上使用Qt 4.8.5和Java 8共享多播接收器端口的类似问题。我可以同时运行多个Qt接收器客户端或多个Java接收器客户端。但是如果我运行一种类型的客户端,另一种类型将不会绑定套接字。

我有一个部分解决方案,即在加入多播组后显式调用setsockopt()以在Qt应用程序中重新设置SO_REUSEADDR标志。这让我在启动Qt客户端后启动Java客户端。所有客户端都正常接收,但在启动第一个Java客户端后,我无法再启动任何Qt客户端,否则绑定将失败。如果我关闭所有Java客户端,我可以打开更多的Qt客户端。但是,只要第一个Java客户端绑定,就不会有更多的Qt客户端绑定。很奇怪。

我的Qt代码现在看起来像这样:

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";

我没有Java客户端的源代码,但我被告知它以推荐的方式使用java.net.MulticastSocket类。