0

2 台のコンピューターのいずれかで実行できるアプリ X がありますが、一度に 1 台しか実行できません。Python で記述された別のアプリ Y があります。この 2 つの IP アドレスから、アプリ X (存在する場合) を実行しているコンピューターを特定する必要があります。ポートでリッスンし、データを受信するたびに「Hello」で応答する UDP サービスを使用することで、これを部分的に解決しました。クライアントは、各アドレスのアプリ X ポートにデータを送信しようとすることができ、応答があれば、そのコンピューターでアプリケーションが実行されていることがわかります。

これまでの私のコードは次のようになります。

 def ipaddress(self):
    """Test which side responds on the status port."""
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        s.settimeout(5)
        s.sendto("status", (ADDR_A, PORT))
        s.recvfrom(1024)
    except socket.timeout:
        try:
            s.sendto("status", (ADDR_B, PORT))
            s.recvfrom(1024)
        except:
            pass
        else:
            return ADDR_B
    else:
        return ADDR_A
    finally:
        s.close()
    return None

この関数の問題は、アプリ X を実行しているコンピューターと通信したいときに定期的に呼び出されることです。常に最初に ADDR_A をテストし、アプリ X を実行していない場合は、ADDR_B を試す前にソケットがタイムアウトするのを待つ必要があります。頻繁に起こることではありませんが、再試行するたびにアプリ X がコンピューターを切り替える可能性があります。

より良い方法はありますか?両方のコンピューターに並行して接続し、一方が応答するとすぐに戻ることができるかどうか疑問に思っています。または、関数が最後に呼び出されたときに最初に応答した IP アドレスをキャッシュする必要がありますか? これらまたは他のアイデアをどのようにコーディングしますか?

ありがとう。

編集:これは、選択を使用した私の改訂されたコードです:

def ipaddress(addr_a, addr_b, timeout=5):
    """Test which side responds on the status port."""

    # Create UDP sockets for each address 
    socks = [ socket.socket(socket.AF_INET, socket.SOCK_DGRAM),
              socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
              ]

    # Send some data to each socket 
    for sock, addr in zip(socks, (addr_a, addr_b)):
        sock.connect(addr)  # do explicit connect so getpeername works
        sock.send("status")

    # Wait for the first to respond if any
    while socks:
        waiting = select.select(socks, [], socks, timeout)[0]
        if waiting:
            for sock in waiting:
                try:
                    data = sock.recv(1024)
                    if data:
                        return sock.getpeername()[0]
                except Exception, e:
                    # Occasionally get [Errno 10054] which means socket isn't really
                    # available, so see if other responds instead...
                    socks.remove(sock)
        else:
            break   # timeout occurred
    return None
4

1 に答える 1

1

2 台のコンピューターを並行して調べるために探している機能を正確に提供するselect.select()を確認する必要があります。

于 2013-07-25T15:03:16.090 に答える