2012-12-02 9 views
10

Abbiamo un software esistente che trasmette periodicamente pacchetti UDP a una porta specifica (7125) nella subnet locale (x.x.x.255). Abbiamo un software di monitoraggio in esecuzione su HP-UX (11.11) che è in grado di ricevere questi pacchetti senza problemi. Tuttavia, dopo aver trasferito il software di monitoraggio su Linux (RHEL 6.1), abbiamo scoperto che non riceve i pacchetti di trasmissione. tcpdump mostra i pacchetti che arrivano sull'host Linux, ma il kernel non li invia attraverso il nostro software.Ricezione di pacchetti broadcast UDP su Linux

Ho utilizzato un paio di script python 2.x che simulano le API socket chiamate che il software di monitoraggio utilizza per testare diversi scenari. Il kernel Linux passa i pacchetti al software del ricevitore se il mittente usa unicast (10.1.0.5), ma non trasmesso (10.1.0.255). Ho cercato sul Web per diversi giorni e non ho trovato nessuno con lo stesso problema. Qualche idea?

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

Il ricevitore non deve "legare" all'indirizzo di broadcast o "INADDR_BROADCAST" (255.255.255.255, il 'INADDR_ANY' di trasmissione)? Cioè, oltre all'impostazione dell'opzione 'SO_BROADCAST' (su entrambi i lati), come stai già facendo. Stai controllando i codici di errore/di ritorno di tutte queste chiamate di sistema socket? –

+0

@MatthewHall aha, il binding all'indirizzo di broadcast funziona! Immagino che questo significhi che Linux ti faccia scegliere tra unicast e broadcast? Siamo in grado di associare a 'INADDR_ANY' e ricevere pacchetti unicast e broadcast su HP-UX. – goose

+0

Sì, sembra che tu debba scegliere. Ho pubblicato una risposta canonica alla tua domanda. Tuttavia, sono un po 'confuso dal fatto che il comportamento differisca su Linux da HP-UX (anche se ci sono degli argomenti sul perché la separazione tra broadcast e unicast sarebbe preferibile). Per me, questo suggerisce che non sappiamo tutto, e bene, è inaccettabile come al solito. Sono tentato di scrivere un paio di programmi di test in C per arricchire completamente le opzioni di trasmissione su Linux, anche se non ho HP-UX ... Fino ad allora, spero che la mia risposta lo copra. –

risposta

13

Beh, mi ha suggerito questa risposta in un commento, e si è dimostrata corretta nella pratica. Vorrei approfondire ulteriormente le sfumature circostanti con il mio codice, ma questo è il caso canonico più vicino.

Oltre a impostare l'opzione SO_BROADCAST presa su entrambi i lati (come si sta già facendo in modo corretto), è inoltre necessario vincolare il proprio ricevitore per l'indirizzo di broadcast (ad esempio, INADDR_BROADCAST, che è 255.255.255.255 ed essenzialmente serve lo stesso ruolo come INADDR_ANY per unicast).

A quanto pare, nella configurazione di HP-UX del manifesto originale, un socket UDP associato a un indirizzo unicast (o INADDR_ANY, in particolare), ma con l'opzione set SO_BROADCAST presa otterrà comunque tutti i datagrammi UDP indirizzati all'indirizzo di trasmissione locale così come il traffico unicast diretto all'host.

Sotto Linux, questo non è il caso. Il binding di un socket UDP, anche se SO_BROADCAST -enabled, a INADDR_ANY non è sufficiente per ricevere sia datagrammi unicast che broadcast sulla porta associata. È possibile utilizzare un socket -ingresso separato per il traffico di trasmissione.

+3

La soluzione per noi era in realtà il collegamento all'indirizzo di subnet broadcast e non "INADDR_BROADCAST".Inoltre, eseguiamo un ambiente simulato in cui vogliamo ricevere un unicast anziché broadcast, quindi questa non era la soluzione definitiva. Tuttavia, se modifichi "INADDR_BROADCAST", farò clic sul segno di spunta. – goose

+0

Per curiosità, è stato documentato ovunque? – Clay