0

ネットワーク上でマルチキャスト データを送信するハードウェア デバイスがあります。データを受信して​​印刷するPythonスクリプトを作成しました。ただし、Windows XP PC でのみ動作し、Ubuntu Linux 10.04 PC では動作しないことがわかりました。Linux では、何も受信されません。while ループを一周するだけで、データが受信されることはありません。私のコードは以下に掲載されています。これが Linux で動作しない理由がわかりますか? ありがとう、ラブ。

# Multicast client
# Adapted from: http://chaos.weblogs.us/archives/164
# on 05/03/2013

import socket

ANY = "0.0.0.0" 
MCAST_ADDR = "224.0.33.154"
MCAST_PORT = 31800

# Create a UDP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)

# Allow multiple sockets to use the same PORT number
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

# Bind to the port that we know will receive multicast data
sock.bind((ANY,MCAST_PORT))

# Tell the kernel that we are a multicast socket
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)

# Tell the kernel that we want to add ourselves to a multicast group
# The address for the multicast group is the third param
status = sock.setsockopt(socket.IPPROTO_IP,
socket.IP_ADD_MEMBERSHIP,
socket.inet_aton(MCAST_ADDR) + socket.inet_aton(ANY));

# setblocking(0) is equiv to settimeout(0.0) which means we poll the socket.
# But this will raise an error if recv() or send() can't immediately find or send data. 
sock.setblocking(0)

while 1:
    try:
        data, addr = sock.recvfrom(1024)
    except socket.error as e:
        pass
    else:
        print "From: ", addr
        print "Data: ", data

以下は、私の Windows PC からの出力例です。

From:  ('0.0.0.0', 31801)
Data:  EDCP

リモート ハードウェア デバイスには IP アドレスがなく、アドレス 0.0.0.0 を使用していることに注意してください。

編集:これは私の Windows ラップトップでも機能しないことがわかりました。そのため、OS に固有のものではないようです。さらに、別のスクリプトを実行して、マルチキャスト データを同じマルチキャスト アドレスとポートに送信しようとしました。1 台の PC から送信でき、他のすべての PC は受信スクリプトを使用して正しく受信できます。しかし、問題のハードウェア デバイスからデータを受信できるのは、私の 1 台の Windows PC だけです。それがイーサネットアダプターまたはそれらの構成に関係しているのかどうか疑問に思っています。ハードウェア デバイスの IP アドレスが 0.0.0.0 であり、これらのイーサネット アダプタおよび/または受信スクリプトがこのアドレスでメッセージを受信するように指示される必要があるという事実と関係があるのでしょうか? Linux PC で Wireshark を実行すると、ハードウェア デバイスからのデータが表示されます。

4

2 に答える 2

0

私はこれと同じ問題を2日間戦いました。Wiresharkはパケットを確認しましたが、私のコードは確認しませんでした。さまざまな情報源からのおそらく「決定的な」答えはどれも私には役立たなかった。キーはhttps://serverfault.com/questions/163244/linux-kernel-not-passing-through-multicast-udp-packetsから取得されました。

「ipmaddr」を実行すると、自分のコードと同様のコードがどのインターフェイスにもマルチキャストアドレスを追加していないことがわかりました。smcrouteで強制的に追加しました(上記のリンクを参照)。まだ喜びはありません。パケットの送信元IPは172.22です...インターフェイスは172.17です...そのNICに172.22アドレスを追加しました。ビンゴ!これで、私のコードがパケットを受信しました。

では、smcrouteなしでプログラムを動作させる方法は?私はsetsockopt()呼び出しをコメントアウトしました。まだ働いた。マルチキャストアドレスをsmcrouteでリンク解除しました-失敗しました。setsockopt()呼び出しのコメントを外し、「ANY」を私の172.22アドレスに置き換えました。成功!

概要:

  1. 着信パケットと同じネットワークセグメントにIPがあることを確認してください。
  2. INADDR_ANYの代わりに、IP_ADD_MEMBERSHIP呼び出しでそのアドレスを使用します。

NICが1つしかない場合は、2)を実行する必要がない可能性があります。私は3つ持っているので、やらなければなりません。

密接な関係がある場合は、Ubuntu12.04を使用しています。他の人が説明しているように、デフォルトの/etc/sysctl.conf設定を変更する必要はありませんでした。やってみました。それらは役に立たなかったので、私はそれらをインストールのデフォルトにリセットしました。

于 2013-03-08T16:58:00.287 に答える
0

代わりに、マルチキャストグループアドレスにバインドしてみてください。

sock.bind((MCAST_ADDR,MCAST_PORT))

また、受信者にマルチキャストTTLを設定する必要はありません。これは送信者用であり、オプションです。

于 2013-03-07T19:46:51.583 に答える