2012-12-02 23 views
10

UDP paketlerini belirli bir bağlantı noktasına (7125) periyodik olarak yerel alt ağda (x.x.x.255) yayımlayan mevcut bir yazılımımız var. HP-UX (11.11) üzerinde çalışan ve bu paketleri hiçbir sorunla karşılayamayan izleme yazılımımız var. Bununla birlikte, izleme yazılımını Linux'a (RHEL 6.1) yükledikten sonra, yayın paketlerini almadığını tespit ettik. tcpdump, Linux ana bilgisayarına gelen paketleri gösterir, ancak çekirdek onları yazılımımıza göndermez.Linux'ta UDP yayın paketlerini alma

İzleme yazılımının farklı senaryoları test etmek için kullandığı soket API'sini taklit eden birkaç python 2.x betiği kullanıyorum. Linux çekirdeği, gönderici tek noktaya yayın (10.1.0.5) kullanıyorsa, ancak yayınlamıyorsa (10.1.0.255) paketleri alıcı yazılımına geçirir. İnterneti birkaç gün boyunca araştırıyorum ve aynı sorunu olan kimseyi bulamadım. Herhangi bir fikir?

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

Alıcınızın yayın adresine veya 'INADDR_BROADCAST' (255.255.255.255, 'INADDR_ANY 'yayını)' bağlanması gerekmez mi? Yani, halihazırda yaptığınız gibi, "SO_BROADCAST" seçeneğini (her iki tarafta) ayarlamaya ek olarak. Tüm bu soket sistem çağrılarının hata/dönüş kodlarını kontrol ediyor musunuz? –

+0

@MatthewHall aha, yayın adresine bağlanıyor! Bu, Linux'un tek noktaya yayın ve yayın arasında seçim yapabilmeniz anlamına mı geliyor? INADDR_ANY öğesine bağlanabilir ve HP-UX'te hem tek noktaya yayın hem de yayın paketleri alabiliriz. – goose

+0

Evet, seçmen gereken gibi görünüyor. Şimdi sorunuza kanonik bir cevap gönderdim. Bununla birlikte, davranışın neden Linux'ta HP-UX'den farklılık gösterdiğine biraz şaşırdım (ancak yayın ve tek noktaya yayın ayırmanın neden tercih edileceğine dair argümanlar olsa da). Bana göre, bu her şeyi bilmediğimizi ve her zamanki gibi kabul edilemez olduğunu gösteriyor. HP-UX'im olmasa da, Linux'taki yayın seçeneklerini tamamen ortadan kaldırmak için C'ye bir çift test programı yazmaya başladım ... O zamana kadar, umarım cevabım bu konuyu kapsar. –

cevap

13

Eh, bir yorum bu cevabı önerdi ve pratikte doğru kanıtladı. Çevremdeki nüansları kendi kodumla daha fazla araştırmak istiyorum, ancak bu, kanonik vakalara daha yakın.

, ayrıca yayın adresine alıcısını bağlamak gerekir (zaten doğru yapıyorsun gibi) her iki tarafta SO_BROADCAST soket seçeneği ayarlamaya ek olarak (örneğin, esasen 255.255.255.255 ve INADDR_BROADCAST, aynı rolü vermektedir tek noktaya yayın için INADDR_ANY).

Görünüşe göre, gönderen kullanıcı, (özellikle, ya INADDR_ANY) Bir özgün adres bağlı bir UDP soket HP-UX yapılandırmasında ama SO_BROADCAST soket seçeneği ayarlanmış hala tüm UDP datagramları yerel yayın adresine gönderilen alacak ana bilgisayara yönlendirilen tek noktaya yayın trafiği.

Linux altında, durum böyle değil. Bir UDP soketinin bağlanması, SO_BROADCAST etkinleştirilmiş olsa bile INADDR_ANY için bağlanan bağlantı noktasında hem tek noktaya yayın hem de yayın datagramlarını almak için yetersizdir. Bir yayın trafiği için ayrı bir INADDR_BROADCAST -bound SO_BROADCAST soketi kullanabilirsiniz.

+3

Bizim için çözüm aslında INADDR_BROADCAST değil, alt ağ yayın adresine bağlandı.Ayrıca, yayın yerine tek noktaya yayın almak istediğimiz simüle edilmiş bir ortam kullanıyoruz, bu yüzden bu nihai çözüm değildi. Ancak, INADDR_BROADCAST'ı düzenlerseniz onay işaretini tıklarım. – goose

+0

Merak etme, burası herhangi bir yerde belgelendi mi? – Clay