간단한 Python UDP 서버: localhost 이외의 클라이언트로부터 패킷을 수신하는 데 문제가 있습니다.
IPv6을 통해 데이터그램을 수신하려고 합니다. 제가 관심을 갖는 뉴스는 다음과 같습니다.
$ sudo tcpdump | grep 20001
[sudo] password for miroslavv:
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
13:00:59.981338 IP6 fd01:e671:2015:5c01:a00:27ff:fe50:275f.20001 > ff05:e671:2015:5c01:a00:27ff:fe50:275f.20001: UDP, length 86
13:00:59.981348 IP6 fd01:e671:2015:5c01:a00:27ff:fe50:275f.20001 > ff05:e671:2015:5c01:a00:27ff:fe50:275f.20001: UDP, length 47
13:00:59.981733 IP6 fd01:e671:2015:5c01:a00:27ff:fe50:275f.20001 > ff05:e671:2015:5c01:a00:27ff:fe50:275f.20001: UDP, length 114
13:00:59.981744 IP6 fd01:e671:2015:5c01:a00:27ff:fe50:275f.20001 > ff05:e671:2015:5c01:a00:27ff:fe50:275f.20001: UDP, length 67
13:00:59.981940 IP6 fd01:e671:2015:5c01:a00:27ff:fe50:275f.20001 > ff05:e671:2015:5c01:a00:27ff:fe50:275f.20001: UDP, length 60
13:00:59.982276 IP6 fd01:e671:2015:5c01:a00:27ff:fe50:275f.20001 > ff05:e671:2015:5c01:a00:27ff:fe50:275f.20001: UDP, length 47
13:00:59.982492 IP6 fd01:e671:2015:5c01:a00:27ff:fe50:275f.20001 > ff05:e671:2015:5c01:a00:27ff:fe50:275f.20001: UDP, length 47
13:00:59.982656 IP6 fd01:e671:2015:5c01:a00:27ff:fe50:275f.20001 > ff05:e671:2015:5c01:a00:27ff:fe50:275f.20001: UDP, length 47
13:00:59.982974 IP6 fd01:e671:2015:5c01:a00:27ff:fe50:275f.20001 > ff05:e671:2015:5c01:a00:27ff:fe50:275f.20001: UDP, length 69
13:00:59.982985 IP6 fd01:e671:2015:5c01:a00:27ff:fe50:275f.20001 > ff05:e671:2015:5c01:a00:27ff:fe50:275f.20001: UDP, length 111
13:00:59.983335 IP6 fd01:e671:2015:5c01:a00:27ff:fe50:275f.20001 > ff05:e671:2015:5c01:a00:27ff:fe50:275f.20001: UDP, length 152
내 플랫폼은 테스트용 Debian입니다. 나는 파이썬을 시도했다예, 그들은 같은 기계에서 서로 완벽하게 통신하는 것 같습니다. 그러나 위에 나열된 데이터그램을 수신하도록 서버를 구성하면 서버가 정지됩니다 recv()
.
방화벽 설정:
$ sudo iptables -L
[sudo] password for miroslavv:
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
나는 IPv6을 가지고 있습니다 :
$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.42.92 netmask 255.255.248.0 broadcast 192.168.47.255
inet6 fd01:e671:2015:e3ff:219:fff:fe26:a27e prefixlen 48 scopeid 0x0<global>
inet6 fe80::219:fff:fe26:a27e prefixlen 64 scopeid 0x20<link>
ether 00:19:0f:26:a2:7e txqueuelen 1000 (Ethernet)
RX packets 3360785 bytes 943676498 (899.9 MiB)
RX errors 0 dropped 6185 overruns 0 frame 0
TX packets 473236 bytes 77103917 (73.5 MiB)
TX errors 1 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1 (Local Loopback)
RX packets 140 bytes 7912 (7.7 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 140 bytes 7912 (7.7 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
netcat
또한 침묵합니다:
$ netcat -u -l -p20001
흥미로운 관찰이 이어집니다. 메시지를 읽기 위해 C++ 코드를 얻었습니다.만약에boost::asio
동일한 IP와 포트에서 동시에 읽습니다. 향상된 폴링을 중지하면 내 코드도 메시지 수신을 중지합니다.
나는 여러 가지 샘플 C 프로그램을 시도했지만 누구로부터도 단 하나의 UDP 패킷도 수신할 수 없습니다.1,2,삼,4.
여기서 무슨 일이 일어나고 있는 걸까요?
답변1
사실 멀티캐스트 그룹에 가입할 기회를 놓쳤어요. ipv6 멀티캐스트의 예는 매우 드물며, 테스트된 코드는 다음과 같습니다.
struct addrinfo hint {}, *res;
hint.ai_flags = AI_PASSIVE;
hint.ai_family = AF_INET6;
hint.ai_socktype = SOCK_DGRAM;
getaddrinfo( server._rep.c_str(), std::to_string( port ).c_str(), &hint, &res )
mreq.ipv6mr_multiaddr = reinterpret_cast< sockaddr_in6* >( res->ai_addr )->sin6_addr;
mreq.ipv6mr_interface if_nametoindex( iface.c_str();
setsockopt( _fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (void*)mreq, sizeof( mreq ) )
추신: 이 주제에 대한 몇 가지 유용한 리소스:
http://www.iitk.ac.in/LDP/HOWTO/Multicast-HOWTO.html#toc6
http://docs.oracle.com/cd/E19253-01/817-4415/sockets-149/index.html