복붙노트

[PYTHON] 어떻게 파이썬에서 UDP 멀티 캐스트합니까?

PYTHON

어떻게 파이썬에서 UDP 멀티 캐스트합니까?

파이썬에서 UDP 멀티 캐스트를 보내고받는 방법은 무엇입니까? 표준 라이브러리가 있습니까?

해결법

  1. ==============================

    1.이것은 나를 위해 작동합니다 :

    이것은 나를 위해 작동합니다 :

    받다

    import socket
    import struct
    
    MCAST_GRP = '224.1.1.1'
    MCAST_PORT = 5007
    IS_ALL_GROUPS = True
    
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    if IS_ALL_GROUPS:
        # on this port, receives ALL multicast groups
        sock.bind(('', MCAST_PORT))
    else:
        # on this port, listen ONLY to MCAST_GRP
        sock.bind((MCAST_GRP, MCAST_PORT))
    mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY)
    
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
    
    while True:
      print sock.recv(10240)
    

    보내다

    import socket
    
    MCAST_GRP = '224.1.1.1'
    MCAST_PORT = 5007
    # regarding socket.IP_MULTICAST_TTL
    # ---------------------------------
    # for all packets sent, after two hops on the network the packet will not 
    # be re-sent/broadcast (see https://www.tldp.org/HOWTO/Multicast-HOWTO-6.html)
    MULTICAST_TTL = 2
    
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, MULTICAST_TTL)
    sock.sendto("robot", (MCAST_GRP, MCAST_PORT))
    

    이것은 작동하지 않는 http://wiki.python.org/moin/UdpCommunication의 예제를 기반으로합니다.

    내 시스템은 ... Linux 2.6.31-15- 일반 # 50-Ubuntu SMP Tue Nov 10 14:54:29 UTC 2009 i686 GNU / Linux 파이썬 2.6.4

  2. ==============================

    2.멀티 캐스트 그룹에 브로드 캐스트하는 멀티 캐스트 보낸 사람 :

    멀티 캐스트 그룹에 브로드 캐스트하는 멀티 캐스트 보낸 사람 :

    #!/usr/bin/env python
    
    import socket
    import struct
    
    def main():
      MCAST_GRP = '224.1.1.1'
      MCAST_PORT = 5007
      sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
      sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)
      sock.sendto('Hello World!', (MCAST_GRP, MCAST_PORT))
    
    if __name__ == '__main__':
      main()
    

    멀티 캐스트 그룹에서 읽고 콘솔에 16 진수 데이터를 인쇄하는 멀티 캐스트 수신기 :

    #!/usr/bin/env python
    
    import socket
    import binascii
    
    def main():
      MCAST_GRP = '224.1.1.1' 
      MCAST_PORT = 5007
      sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
      try:
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
      except AttributeError:
        pass
      sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32) 
      sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 1)
    
      sock.bind((MCAST_GRP, MCAST_PORT))
      host = socket.gethostbyname(socket.gethostname())
      sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton(host))
      sock.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, 
                       socket.inet_aton(MCAST_GRP) + socket.inet_aton(host))
    
      while 1:
        try:
          data, addr = sock.recvfrom(1024)
        except socket.error, e:
          print 'Expection'
          hexdata = binascii.hexlify(data)
          print 'Data = %s' % hexdata
    
    if __name__ == '__main__':
      main()
    
  3. ==============================

    3.더 나은 사용 :

    더 나은 사용 :

    sock.bind((MCAST_GRP, MCAST_PORT))
    

    대신에:

    sock.bind(('', MCAST_PORT))
    

    ... 같은 포트에있는 여러 mcast 그룹을 청취하고 싶다면 모든 청취자에게 모든 메시지를 보냅니다.

  4. ==============================

    4.멀티 캐스트 그룹에 가입하려면 Python은 기본 OS 소켓 인터페이스를 사용합니다. 파이썬 환경의 이식성과 안정성으로 인해 많은 소켓 옵션이 네이티브 소켓 setsockopt 호출로 직접 전달됩니다. 그룹 멤버십 가입 및 삭제와 같은 멀티 캐스트 작동 모드는 setsockopt를 통해서만 수행 할 수 있습니다.

    멀티 캐스트 그룹에 가입하려면 Python은 기본 OS 소켓 인터페이스를 사용합니다. 파이썬 환경의 이식성과 안정성으로 인해 많은 소켓 옵션이 네이티브 소켓 setsockopt 호출로 직접 전달됩니다. 그룹 멤버십 가입 및 삭제와 같은 멀티 캐스트 작동 모드는 setsockopt를 통해서만 수행 할 수 있습니다.

    멀티 캐스트 IP 패킷을 수신하기위한 기본 프로그램은 다음과 같습니다.

    from socket import *
    
    multicast_port  = 55555
    multicast_group = "224.1.1.1"
    interface_ip    = "10.11.1.43"
    
    s = socket(AF_INET, SOCK_DGRAM )
    s.bind(("", multicast_port ))
    mreq = inet_aton(multicast_group) + inet_aton(interface_ip)
    s.setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP, str(mreq))
    
    while 1:
        print s.recv(1500)
    

    먼저 소켓을 생성하고 바인드하며 triggers는 setsockopt를 실행하여 멀티 캐스트 그룹에 참여를 트리거합니다. 결국 패킷을 영원히받습니다.

    멀티 캐스트 IP 프레임을 보내는 것은 간단합니다. 시스템에 단일 NIC가있는 경우 그러한 패킷을 보내는 것은 일반적인 UDP 프레임 전송과 다릅니다. 주의해야 할 것은 sendto () 메소드에서 올바른 대상 IP 주소를 설정하는 것입니다.

    사실 인터넷에서 여러 가지 예가 우연히 발견되었습니다. 공식 파이썬 문서에서도. 모두에 대한 문제는 struct.pack을 잘못 사용하고 있습니다. 일반적인 예제에서는 4sl을 형식으로 사용하며 실제 OS 소켓 인터페이스 구조와 일 치하지 않습니다.

    나는 파이썬 소켓 객체에 setsockopt를 호출 할 때 후드에서 일어나는 일을 설명하려고 노력할 것이다.

    파이썬은 setsockopt 메소드 호출을 네이티브 C 소켓 인터페이스로 전달합니다. 리눅스 소켓 문서 (man 7 ip 참조)는 IP_ADD_MEMBERSHIP 옵션을위한 두 가지 형태의 ip_mreqn 구조체를 소개한다. 가장 짧은 형식은 8 바이트 길이이며 더 긴 것은 12 바이트 길이입니다. 위의 예는 8 바이트 setsockopt 호출을 생성합니다. 여기서 fist는 멀티 캐스트 그룹 및 두 번째 interface_ip를 바이트로 정의합니다.

  5. ==============================

    5.py-multicast를 살펴보십시오. 네트워크 모듈은 인터페이스가 멀티 캐스트를 지원하는지 확인할 수 있습니다 (Linux의 경우).

    py-multicast를 살펴보십시오. 네트워크 모듈은 인터페이스가 멀티 캐스트를 지원하는지 확인할 수 있습니다 (Linux의 경우).

    import multicast
    from multicast import network
    
    receiver = multicast.MulticastUDPReceiver ("eth0", "238.0.0.1", 1234 )
    data = receiver.read()
    receiver.close()
    
    config = network.ifconfig()
    print config['eth0'].addresses
    # ['10.0.0.1']
    print config['eth0'].multicast
    #True - eth0 supports multicast
    print config['eth0'].up
    #True - eth0 is up
    

    아마도 IGMP가 보이지 않는 문제는 멀티 캐스트를 지원하지 않는 인터페이스 때문 이었습니까?

  6. ==============================

    6.http://twistedmatrix.com/trac/에서이 작업을 수행 할 수있는 프레임 워크가 있습니다. 다음은 https://twistedmatrix.com/documents/12.2.0/core/howto/udp.html 예제입니다.

    http://twistedmatrix.com/trac/에서이 작업을 수행 할 수있는 프레임 워크가 있습니다. 다음은 https://twistedmatrix.com/documents/12.2.0/core/howto/udp.html 예제입니다.

  7. ==============================

    7.다른 답변의 코드에서 미묘한 점을 설명하기위한 또 다른 대답은 다음과 같습니다.

    다른 답변의 코드에서 미묘한 점을 설명하기위한 또 다른 대답은 다음과 같습니다.

    멀티 캐스트 (UDP) 소켓을 바인딩한다는 것은 무엇을 의미합니까? 멀티 캐스트 작동 방식에 대한 자세한 정보

    멀티 캐스트 수신기 :

    import socket
    import struct
    import argparse
    
    
    def run(groups, port, iface=None, bind_group=None):
        # generally speaking you want to bind to one of the groups you joined in
        # this script,
        # but it is also possible to bind to group which is added by some other
        # programs (like another python program instance of this)
    
        # assert bind_group in groups + [None], \
        #     'bind group not in groups to join'
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
    
        # allow reuse of socket (to allow another instance of python running this
        # script binding to the same ip/port)
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    
        sock.bind(('' if bind_group is None else bind_group, port))
        for group in groups:
            mreq = struct.pack(
                '4sl' if iface is None else '4s4s',
                socket.inet_aton(group),
                socket.INADDR_ANY if iface is None else socket.inet_aton(iface))
    
            sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
    
        while True:
            print(sock.recv(10240))
    
    
    if __name__ == '__main__':
        parser = argparse.ArgumentParser()
        parser.add_argument('--port', type=int, default=19900)
        parser.add_argument('--join-mcast-groups', default=[], nargs='*',
                            help='multicast groups (ip addrs) to listen to join')
        parser.add_argument(
            '--iface', default=None,
            help='local interface to use for listening to multicast data; '
            'if unspecified, any interface would be chosen')
        parser.add_argument(
            '--bind-group', default=None,
            help='multicast groups (ip addrs) to bind to for the udp socket; '
            'should be one of the multicast groups joined globally '
            '(not necessarily joined in this python program) '
            'in the interface specified by --iface. '
            'If unspecified, bind to 0.0.0.0 '
            '(all addresses (all multicast addresses) of that interface)')
        args = parser.parse_args()
        run(args.join_mcast_groups, args.port, args.iface, args.bind_group)
    

    샘플 사용법 : (두 개의 콘솔에서 아래를 실행하고 자신 만의 --iface (멀티 캐스트 데이터를받는 인터페이스와 같아야 함)를 선택하십시오.)

    python3 multicast_recv.py --iface = '192.168.56.102'- 가입 - 캐스트 - 그룹 '224.1.1.1' '224.1.1.2' '224.1.1.3'- 바인드 그룹 '224.1.1.2'

    python3 multicast_recv.py --iface = '192.168.56.102'- 가입 - 캐스트 - 그룹 '224.1.1.4'

    멀티 캐스트 발신자 :

    import socket
    import argparse
    
    
    def run(group, port):
        MULTICAST_TTL = 20
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
        sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, MULTICAST_TTL)
        sock.sendto(b'from multicast_send.py: ' +
                    f'group: {group}, port: {port}'.encode(), (group, port))
    
    
    if __name__ == '__main__':
        parser = argparse.ArgumentParser()
        parser.add_argument('--mcast-group', default='224.1.1.1')
        parser.add_argument('--port', default=19900)
        args = parser.parse_args()
        run(args.mcast_group, args.port)
    

    샘플 사용법 : # 수신자가 아래의 멀티 캐스트 그룹 주소에 바인드하고 일부 프로그램 요청이 해당 그룹에 참여한다고 가정합니다. 이 경우를 단순화하기 위해 수신자와 발신자가 동일한 서브넷에 있다고 가정합니다.

    python3 multicast_send.py --mcast-group '224.1.1.2'

    python3 multicast_send.py --mcast-group '224.1.1.4'

  8. ==============================

    8.Solaris에서 tolomea의 클라이언트 코드를 작동 시키려면 IP_MULTICAST_TTL 소켓 옵션의 ttl 값을 부호없는 char으로 전달해야합니다. 그렇지 않으면 오류가 발생합니다. 이것은 Solaris 10 및 11에서 나에게 도움이되었다.

    Solaris에서 tolomea의 클라이언트 코드를 작동 시키려면 IP_MULTICAST_TTL 소켓 옵션의 ttl 값을 부호없는 char으로 전달해야합니다. 그렇지 않으면 오류가 발생합니다. 이것은 Solaris 10 및 11에서 나에게 도움이되었다.

    import socket
    import struct
    
    MCAST_GRP = '224.1.1.1'
    MCAST_PORT = 5007
    ttl = struct.pack('B', 2)
    
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl)
    sock.sendto("robot", (MCAST_GRP, MCAST_PORT))
    
  9. ==============================

    9.tolomea의 대답이 나를 위해 일했습니다. 나는 그것을 socketserver.UDPServer에 해킹했다.

    tolomea의 대답이 나를 위해 일했습니다. 나는 그것을 socketserver.UDPServer에 해킹했다.

    class ThreadedMulticastServer(socketserver.ThreadingMixIn, socketserver.UDPServer):
        def __init__(self, *args):
            super().__init__(*args)
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.socket.bind((MCAST_GRP, MCAST_PORT))
            mreq = struct.pack('4sl', socket.inet_aton(MCAST_GRP), socket.INADDR_ANY)
            self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
    
  10. ==============================

    10.멀티 캐스트 트래픽은 IP 주소를 제외하고 일반 UDP와 다르지 않습니다. 표준 소켓 라이브러리를 살펴보십시오. 당신은 소켓에서 빌드하고 사용하기 쉬운 것을 찾을 수있을 것입니다.

    멀티 캐스트 트래픽은 IP 주소를 제외하고 일반 UDP와 다르지 않습니다. 표준 소켓 라이브러리를 살펴보십시오. 당신은 소켓에서 빌드하고 사용하기 쉬운 것을 찾을 수있을 것입니다.

  11. from https://stackoverflow.com/questions/603852/how-do-you-udp-multicast-in-python by cc-by-sa and MIT license