2012-12-02 19 views
10

Mamy istniejące oprogramowanie, które okresowo nadaje pakiety UDP do określonego portu (7125) w lokalnej podsieci (x.x.x.255). Mamy oprogramowanie monitorujące działające na HP-UX (11.11), które może odbierać te pakiety bez problemu. Jednak po przeniesieniu oprogramowania monitorującego na Linuksa (RHEL 6.1) stwierdziliśmy, że nie otrzymuje pakietów emisji. tcpdump pokazuje pakiety przychodzące na hosta Linux, ale jądro nie wysyła ich do naszego oprogramowania.Odbieranie pakietów emisji UDP w systemie Linux

Używam kilku skryptów w języku Python 2.x, które naśladują wywołania interfejsu API gniazda używane przez oprogramowanie monitorujące do testowania różnych scenariuszy. Jądro Linuksa przekazuje pakiety do oprogramowania odbiornika, jeśli nadawca używa unicast (10.1.0.5), ale nie nadaje (10.1.0.255). Przez kilka dni szukałem w internecie i nie znalazłem nikogo z tym samym problemem. Jakieś pomysły?

receiver.py

from __future__ import print_function 
import socket 

localHost = '' 
localPort = 7125 
remoteHost = '10.1.0.5' 
remotePort = 19100 

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) 
s.bind((localHost, localPort)) 
s.connect((remoteHost, remotePort)) 
print('Listening on {0}:{1} for traffic from {2}:{3}'.format(localHost, localPort, remoteHost, remotePort)) 
data = s.recv(1024) 
print('Received: {0}'.format(data)) 
s.close() 

sender.py

from __future__ import print_function 
import socket 
import time 

localHost = '' 
localPort = 19100 
remoteHost = '10.1.0.255' 
remotePort = 7125 

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) 
s.bind((localHost, localPort)) 
s.connect((remoteHost, remotePort)) 
data = 'sending this from {0}:{1} to {2}:{3}'.format(localHost, localPort, remoteHost, remotePort) 
print(data) 
print('2') 
time.sleep(1) 
print('1') 
time.sleep(1) 
s.send(data) 
print('sent at {0}'.format(time.ctime())) 
s.close() 
+2

Czy Twój odbiornik nie musi "bindować" do adresu rozgłoszeniowego lub "INADDR_BROADCAST" (255.255.255.255, "INADDR_ANY" transmisji)? Oznacza to, że oprócz ustawiania opcji 'SO_BROADCAST' (po obu stronach), tak jak już to robisz. Czy sprawdzasz kody błędów/powrotu wszystkich tych wywołań systemu gniazd? –

+0

@MatthewHall aha, wiązanie z adresem broadcast działa! Domyślam się, że to oznacza, że ​​Linux wybiera między emisją jednostkową a emisją? Jesteśmy w stanie powiązać "INADDR_ANY" i odbierać zarówno pakiety emisji pojedynczej, jak i emisji w systemie HP-UX. – goose

+0

Tak, wydaje się, że musisz wybrać. Wysłałem teraz kanoniczną odpowiedź na twoje pytanie. Jestem jednak nieco oszołomiony tym, dlaczego zachowanie różni się w Linuksie od HP-UX (choć istnieją argumenty przemawiające za tym, dlaczego lepsze byłoby rozdzielenie emisji i emisji pojedynczej). Dla mnie to sugeruje, że nie wiemy wszystkiego, i, cóż, to niedopuszczalne jak zwykle. Mam ochotę napisać kilka programów testowych w C, aby w pełni rozwinąć opcje emisji na Linuksie, chociaż nie mam HP-UX ... Do tego czasu mam nadzieję, że moja odpowiedź to obejmie. –

Odpowiedz

13

Cóż, ja zaproponowałem tę odpowiedź w komentarzu, a sprawdziły się w praktyce. Chciałbym dokładniej zbadać otaczające niuanse za pomocą mojego własnego kodu, ale jest to kwestia kanoniczna.

Oprócz ustawienia opcji gniazda po obu stronach (tak jak już to robisz poprawnie), musisz również powiązać swój odbiornik z adresem rozgłoszeniowym (np. INADDR_BROADCAST, który jest 255.255.255.255 i pełni tę samą rolę jako INADDR_ANY dla emisji pojedynczej).

Podobno w konfiguracji HP-UX oryginalnego plakatu, gniazda UDP związanego z adresu unicast (lub INADDR_ANY konkretnie), ale z opcją SO_BROADCAST gniazdo zestawu będzie nadal odbierać wszystkie datagramy UDP skierowana do lokalnego adresu broadcast jak również ruch jednostkowy skierowany na hosta.

Pod Linuksem tak nie jest. Oprawa gniazda UDP, nawet gdy SO_BROADCAST -enabled, na INADDR_ANY jest niewystarczająca do odbioru datagramów emisji pojedynczej i rozgłoszeniowej na przyłączonym porcie. Można użyć osobnego gniazda INADDR_BROADCAST -bound dla ruchu rozgłoszeniowego.

+3

Rozwiązaniem dla nas było w rzeczywistości powiązanie z adresem emisji podsieci, a nie "INADDR_BROADCAST".Ponadto uruchamiamy symulowane środowisko, w którym chcemy odbierać unicast zamiast emisji, więc nie było to najlepsze rozwiązanie. Jednakże, jeśli edytujesz 'INADDR_BROADCAST', kliknę znacznik wyboru. – goose

+0

Z ciekawości, czy to było udokumentowane w dowolnym miejscu? – Clay

Powiązane problemy