동일한 Windows 호스트에서 동일한 멀티캐스트 그룹을 사용하는 여러 애플리케이션

동일한 Windows 호스트에서 동일한 멀티캐스트 그룹을 사용하는 여러 애플리케이션

저는 시작 절차에서 IP 멀티캐스팅을 활용하여 피어를 검색하는 분산 소프트웨어를 설계하는 소프트웨어 엔지니어입니다. 소프트웨어 자체는 서로 다른 실행 모듈로 배포되므로 때로는 동일한 호스트에서 여러 실행 모듈을 실행하는 것이 합리적입니다. Windows가 단일 멀티캐스트 그룹에 가입하는 여러 프로세스를 관리하는 데 능숙하지 않은 것 같기 때문에 이것이 내 문제가 시작되는 곳입니다.

내 목표는 어떤 호스트에서 어떤 실행 파일을 시작할지 자유롭게 선택할 수 있는 것입니다. 그러면 사전 정의된 지식 없이도 실행 파일이 모든 피어(동일한 호스트에 있든 다른 호스트에 있든)를 검색할 수 있습니다.

지금까지 문제 해결에서는 Windows가 동일한 멀티캐스트 그룹을 구독하는 여러 프로세스의 시나리오를 처리하는 방식에 문제가 있음을 나타냅니다. 그 이유는 다음과 같습니다.

  1. 동일한 시스템에서 멀티캐스트 데이터그램을 보내고 받는 데 동일한 프로세스가 사용되는 경우 예상대로 작동합니다. 프로세스는 문제 없이 여러 스레드로 분할될 수 있습니다.

  2. 전송 및 수신을 위해 서로 다른 프로세스를 실행하면 그룹 가입 메시지와 모든 데이터그램이 Wireshark에 표시됨에도 불구하고 수신 프로세스는 아무것도 수신하지 못합니다.

  3. 2에 설명된 시나리오는 청취하기 전에 동일한 소켓을 사용하여 내가 가입한 멀티캐스트 그룹에 패킷을 보내는 경우에 작동합니다. 그런 다음 후자는 지정되지 않은 시간 동안 멀티캐스트 데이터그램을 수신하고 그 후에는 데이터그램 수신만 중지합니다(데이터그램이 오기를 계속 기다림). Wireshark를 사용하여 데이터그램이 네트워크로/에서 전송되는 것이 확인되었습니다.

  4. 최근 조사 결과에 따르면 내가 구독하는 그룹에 정기적으로 멀티캐스트 메시지를 보내면 동일한 호스트의 다른 프로세스에서도 이 멀티캐스트 그룹으로 보낸 데이터그램을 받게 됩니다.

내가 이해하는 한, IP 멀티캐스트는 다음과 같은 통신만 정의합니다.호스트, 들어오는 패킷을 적절한 경로로 리디렉션하는 것은 OS의 책임입니다.애플리케이션. 패킷이 Wireshark에 항상 표시되는 것처럼 보이므로 응용 프로그램이 패킷을 수신하지 못하더라도 Windows는 들어오는 패키지를 처리하지 못하거나 적어도 해당 응용 프로그램에 전달하는 데 실패하는 것 같습니다.

누구든지 내 추론을 확인하거나 거부할 수 있을 뿐만 아니라 이 문제를 해결하는 방법에 대한 올바른 방향을 알려줄 수 있다면 감사하겠습니다. 목표는 동일한 호스트에 있는 여러 응용 프로그램이 단일 멀티캐스트 그룹 채널에 가입하고 데이터를 수신하기 위해 멀티캐스트 그룹에 "정크"를 보낼 필요 없이 메시지를 수신할 수 있도록 하는 것입니다(해결 방법은 포인트 번호로 설명됨). 4).

구현을 위해 Java를 사용하고 있으며 요청 시 여기에 MWE를 게시할 수 있습니다. 그러나 나는 그것이 시나리오에서 프로그래밍으로 초점을 옮길 수 있다는 것을 두려워합니다. 이것은 여기서의 관심사가 아닙니다(내가 추론할 수 있는 것에서).

답변1

OP는 해당 피어에 대한 지식 없이 네트워크에서 피어를 검색하는 방법을 요구하고 있다고 합니다.이 소스mDNS에는 최소한 각 피어의 호스트 이름에 대한 지식이 필요합니다.

결과적으로 mDNS는 설명된 대로 이 문제에 대한 실행 가능한 솔루션이 아닙니다.

에 따라이 답변에, 멀티캐스트에 관해서는 문의하신 내용이 가능합니다. SO_REUSEADDR 소켓 옵션을 사용하는 것이 포함됩니다. 이 소켓 옵션을 사용하면 여러 소켓이 동일한 주소:포트 조합을 수신할 수 있습니다.

  1. 주소는 멀티캐스트 주소입니다. 그리고
  2. SO_RESUSEADDR은 주소:포트 조합에 바인딩을 시도하는 모든 소켓에 설정됩니다.

그러나 따르면이 답변, 각 소켓에도 SO_BROADCAST를 설정해야 할 수도 있는데, 이는 확실히 직관적이지 않습니다! 그러나 Windows에서 Python을 사용하는 내 자체 테스트에서는 이 작업을 수행할 필요가 없었으므로 해당 답변이 얼마나 합법적인지 잘 모르겠습니다. 문제가 발생할 경우를 대비해 언급하겠습니다. 이 내용은 잠재적으로 오래된 것으로 간주하지만 테스트 중입니다. 현재 Windows 10에서는.

다음은 오류를 생성하지 않고 테스트한 코드의 예입니다. 이는 비콘을 사용하여 작업자 프로세스를 브로커 프로세스에 연결하는 자동화된 테스트의 일부입니다. 이 테스트는 단일 노드에서 실행될 때 통과하지만 아직 여러 노드에서는 테스트하지 않았습니다.

import socket, struct

MCAST_GRP = ''
MCAST_PORT = 1234

MULTICAST_TTL = 2

def create_beacon_listener():

    sock = socket.socket(
        socket.AF_INET,
        socket.SOCK_DGRAM,
        socket.IPPROTO_UDP
    )
    sock.setsockopt(
        socket.SOL_SOCKET,
        socket.SO_REUSEADDR,
        1
    )
    sock.setblocking(0)

    sock.bind(( MCAST_GRP, MCAST_PORT ))

    multicast_grp_req = struct.pack(
        "4sl",
        socket.inet_aton(MCAST_GRP),
        socket.INADDR_ANY
    )

    sock.setsockopt(
        socket.IPPROTO_IP,
        socket.IP_ADD_MEMBERSHIP,
        multicast_grp_req
    )
    
    return sock

위의 코드는 원하는 그룹 주소 MCAST_GRP 및 포트 MCAST_PORT에서 청취 소켓을 반환합니다. 그리고 그렇습니다. MCAST_GRP는 빈 문자열로 설정됩니다. 이는 실제로 모든 멀티캐스트 주소 그룹을 수신한다는 의미입니다. 이것은 창이나 내 지식, 아마도 후자의 한계인 것 같습니다.

어느 쪽이든 MCAST_GRP 변수에 특정 주소를 사용하면 오류가 발생하므로 빈 문자열을 사용하면 최소한 OP에서 설명하는 문제를 해결하기 위한 코드를 얻을 수 있습니다.

이 코드는 동일한 프로세스 내에서 여러 번 재사용할 수 있지만 여러 프로세스에서 이를 성공적으로 사용할 수 있는지 아직 테스트하지 않았습니다. 저는 Python의 asyncio 프레임워크를 사용하여 테스트했으므로 동일한 스레드에서 여러 소켓이 수신됩니다.

여담이지만 크로스 플랫폼 지원을 위해 이 코드를 nix 운영 체제에서 작동하도록 할 수도 있으며 해당 시스템에서는 MCAST_GRP를 특정 주소로 설정할 수도 있습니다.

편집하다:

최근에 우연히 접한MS의 이 리소스이는 모두에 바인딩하는 대신 특정 멀티캐스트 그룹 주소를 사용하도록 허용하는 것으로 보이는 예를 제공합니다. multicast_grp_req 변수에 몇 가지 추가 옵션을 설정하는 작업이 포함됩니다. 또한 예제는 Python이 아닌 C++ 코드이지만 요점을 이해할 만큼 유사합니다.

도움이 되었기를 바랍니다 :)

관련 정보