SSDP 検出要求をブロードキャストする Python アプリがあります。検出しようとしているデバイスが常に応答しているとは限らないことに気付きました。Wireshark を使用すると、一部のブロードキャストのみがネットワークに到達していることがわかりました。いくつかのトラブルシューティングの後、問題の原因を SSDP Discovery サービスに切り分けました。このサービスを無効にすると、パケット損失がなくなりました。また、SSDP (239.255.255.250) 以外のマルチキャスト アドレスを使用すると、問題も解決します。そのため、SSDP が発信 UDP ブロードキャストを抑制しているようです。これはなぜですか?おそらく、ブロードキャストを結合したり、トラフィックを制限したりしようとしていますか? Windows 7 を使用しています。OSX では問題は発生しません。
これは、パケット損失を示す簡単なテスト アプリです。両方のインスタンスが同じシステムで実行され、送信側インスタンスは毎秒パケットを送信し、受信側はテストで定義されたパケット数のギャップを報告します。
def testSend():
seqNumber = 0
while True:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 1)
sock.sendto(str(seqNumber), ("239.255.255.250", 1900))
sock.close()
print("Sent Seq #{:4d} [{}]".format(seqNumber, time.ctime()))
seqNumber += 1
time.sleep(1)
def testReceive():
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(("", 1900))
mreq = struct.pack("4sl", socket.inet_aton("239.255.255.250"), socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
expectedSequenceNumber = 0
while True:
response = sock.recv(100)
actualSequenceNumber = int(response)
if actualSequenceNumber == expectedSequenceNumber:
print("Good: Received Seq #{:>4s} [{}]".format(response, time.ctime()))
else:
print("Bad: Expected Seq #{}, Got #{} ({} frames dropped) [{}]".format(expectedSequenceNumber, actualSequenceNumber, actualSequenceNumber - expectedSequenceNumber, time.ctime()))
expectedSequenceNumber = actualSequenceNumber + 1
if sys.argv[1] == 'send':
testSend()
elif sys.argv[1] == 'receive':
testReceive()
Output on receiving side:
Good: Received Seq # 0 [Sun Sep 20 11:01:18 2015]
Good: Received Seq # 1 [Sun Sep 20 11:01:19 2015]
Good: Received Seq # 2 [Sun Sep 20 11:01:20 2015]
Good: Received Seq # 3 [Sun Sep 20 11:01:21 2015]
Good: Received Seq # 4 [Sun Sep 20 11:01:22 2015]
Bad: Expected Seq #5, Got #12 (7 frames dropped) [Sun Sep 20 11:01:30 2015]
Good: Received Seq # 13 [Sun Sep 20 11:01:31 2015]
Good: Received Seq # 14 [Sun Sep 20 11:01:32 2015]
Good: Received Seq # 15 [Sun Sep 20 11:01:33 2015]
Good: Received Seq # 16 [Sun Sep 20 11:01:34 2015]
Good: Received Seq # 17 [Sun Sep 20 11:01:35 2015]
Good: Received Seq # 18 [Sun Sep 20 11:01:36 2015]
Good: Received Seq # 19 [Sun Sep 20 11:01:37 2015]
Good: Received Seq # 20 [Sun Sep 20 11:01:38 2015]
Bad: Expected Seq #21, Got #51 (30 frames dropped) [Sun Sep 20 11:02:09 2015]
Good: Received Seq # 52 [Sun Sep 20 11:02:10 2015]
Good: Received Seq # 53 [Sun Sep 20 11:02:11 2015]
Good: Received Seq # 54 [Sun Sep 20 11:02:12 2015]
Good: Received Seq # 55 [Sun Sep 20 11:02:14 2015]
Good: Received Seq # 56 [Sun Sep 20 11:02:15 2015]
Good: Received Seq # 57 [Sun Sep 20 11:02:16 2015]
Good: Received Seq # 58 [Sun Sep 20 11:02:17 2015]
Good: Received Seq # 59 [Sun Sep 20 11:02:18 2015]
Good: Received Seq # 60 [Sun Sep 20 11:02:19 2015]
Bad: Expected Seq #61, Got #71 (10 frames dropped) [Sun Sep 20 11:02:30 2015]
Good: Received Seq # 72 [Sun Sep 20 11:02:31 2015]
Good: Received Seq # 73 [Sun Sep 20 11:02:32 2015]
Good: Received Seq # 74 [Sun Sep 20 11:02:33 2015]
Good: Received Seq # 75 [Sun Sep 20 11:02:34 2015]
Good: Received Seq # 76 [Sun Sep 20 11:02:35 2015]
Good: Received Seq # 77 [Sun Sep 20 11:02:36 2015]
Good: Received Seq # 78 [Sun Sep 20 11:02:37 2015]
Good: Received Seq # 79 [Sun Sep 20 11:02:38 2015]
Good: Received Seq # 80 [Sun Sep 20 11:02:39 2015]
Bad: Expected Seq #81, Got #110 (29 frames dropped) [Sun Sep 20 11:03:09 2015]
Good: Received Seq # 111 [Sun Sep 20 11:03:10 2015]
Good: Received Seq # 112 [Sun Sep 20 11:03:11 2015]
Good: Received Seq # 113 [Sun Sep 20 11:03:12 2015]
Good: Received Seq # 114 [Sun Sep 20 11:03:13 2015]
Good: Received Seq # 115 [Sun Sep 20 11:03:14 2015]
Good: Received Seq # 116 [Sun Sep 20 11:03:15 2015]
Good: Received Seq # 117 [Sun Sep 20 11:03:16 2015]
Good: Received Seq # 118 [Sun Sep 20 11:03:17 2015]
Good: Received Seq # 119 [Sun Sep 20 11:03:18 2015]
Bad: Expected Seq #120, Got #130 (10 frames dropped) [Sun Sep 20 11:03:30 2015]
Good: Received Seq # 131 [Sun Sep 20 11:03:31 2015]
Good: Received Seq # 132 [Sun Sep 20 11:03:32 2015]
Good: Received Seq # 133 [Sun Sep 20 11:03:33 2015]
Good: Received Seq # 134 [Sun Sep 20 11:03:34 2015]
Good: Received Seq # 135 [Sun Sep 20 11:03:35 2015]
Good: Received Seq # 136 [Sun Sep 20 11:03:36 2015]
編集 (10/06/15): 私は問題の根本原因を突き止めたと思います。Windows SSDP Discovery サービスは、物理ネットワーク インターフェイスが 1 つしか構成されていない、またはオンラインになっているシステムでも、マルチキャスト パケットが送信されるインターフェイスと受信パケットが送信されるインターフェイスを定期的に循環させます。私のシステムには、1 つの有線イーサネット ネットワークと 2 つの仮想 VMware ネットワーク アダプターがあります (私は VM で実行していません。これらはホスト側にあり、有効になっていますが、使用されていません)。上記のユーティリティのソースを変更して、setsockopt(IP_MULTICAST_IF) を介してブロードキャストを送信するインターフェイスと、setsockopt(IP_ADD_MEMBERSHIP) を介してブロードキャストをリッスンするインターフェイスの構成をサポートするようにしました。次に、ユーティリティの 4 つのインスタンスを実行しました。1 つは INADDR_ANY で送信し、1 つは INADDR_ANY で受信し、さらに、VMware 仮想ネットワーク アダプタ (VMnet1 と VMnet8、どちらも独自の製造済み/仮想サブネットで事前構成済み) のそれぞれでリッスンします。INADDR_ANY レシーバー インスタンスでパケットが欠落し始めると、それらが VMware リスナーの 1 つに表示されます。これは、Windows SSDP Discovery サービスがマルチキャスト転送用に設定された既定のアダプターを循環させていることを証明しています。SSDP サービスが無効になっている場合、これは発生しません。ディスカバリー サービスは、すべてのネットワーク インターフェイスで SSDP メッセージをキャッチするためにこれを行っていると思いますが、システムの各インターフェイスに 1 つずつ、複数のソケットを持つだけでなく、これを達成するためにシステムの既定のマルチキャストを変更する必要がある理由は明らかではありません。INADDR_ANY レシーバー インスタンスでパケットが欠落し始めると、それらが VMware リスナーの 1 つに表示されます。これは、Windows SSDP Discovery サービスがマルチキャスト転送用に設定された既定のアダプターを循環させていることを証明しています。SSDP サービスが無効になっている場合、これは発生しません。ディスカバリー サービスは、すべてのネットワーク インターフェイスで SSDP メッセージをキャッチするためにこれを行っていると思いますが、システムの各インターフェイスに 1 つずつ、複数のソケットを持つだけでなく、これを達成するためにシステムの既定のマルチキャストを変更する必要がある理由は明らかではありません。INADDR_ANY レシーバー インスタンスでパケットが欠落し始めると、それらが VMware リスナーの 1 つに表示されます。これは、Windows SSDP Discovery サービスがマルチキャスト転送用に設定された既定のアダプターを循環させていることを証明しています。SSDP サービスが無効になっている場合、これは発生しません。ディスカバリー サービスは、すべてのネットワーク インターフェイスで SSDP メッセージをキャッチするためにこれを行っていると思いますが、システムの各インターフェイスに 1 つずつ、複数のソケットを持つだけでなく、これを達成するためにシステムの既定のマルチキャストを変更する必要がある理由は明らかではありません。
回避策は、シングルホームである他のすべての OS プラットフォームで正常に動作するマルチキャストを処理する従来の方法である INADDR_ANY に依存するのではなく、マルチキャスト送信およびリッスン用に構成するインターフェイスを明示的に設定することです。送信インターフェイスだけでなく受信側も明示的に設定する必要があることに注意してください。これは、ディスカバリ サービスによるデフォルト インターフェイスの循環が、デフォルト送信インターフェイスと、IP マルチキャスト メンバーシップ グループで受け入れられる受信パケットのインターフェイスの両方に適用されるためです。 .