Forum: PC-Programmierung udp: broadcast an allen Netzwerkadaptern


von Matthias L. (Gast)


Lesenswert?

Hallo Leute,

ich habe folgendes vor: Ein in MS VS C++ geschriebenes Programm soll 
einen (beliebigen) UDP-Port öffnen und darüber einen Broadcast ins 
Netzwerk senden. Die Antworten werte ich dann aus. Umgesetzt habe ich 
das etwa so:

- UdpSocket öffnen,
- Mit BeginReceiveFrom und einem Callback über EndReceiveFrom bearbeite 
ich die empfangenen Meldungen.
- Gesendet habe ich mit Sentto.
1
System::Void
2
Trif_Scan::ThreadWork( System::Void )
3
{
4
  //-- Port öffnen ----------------------------------------------------
5
  System::Net::Sockets::Socket^  
6
    UpdSocket = gcnew System::Net::Sockets::Socket
7
                 (  System::Net::Sockets::AddressFamily::InterNetwork,  System::Net::Sockets::SocketType::Dgram,                                          System::Net::Sockets::ProtocolType::Udp );
8
  UpdSocket->EnableBroadcast = true;
9
  UpdSocket->Bind( gcnew System::Net::IPEndPoint ( System::Net::IPAddress::Any, 65000 ) );   // <== HIER
10
11
  UpdSocket->BeginReceiveFrom( ... );
12
13
  System::Net::IPEndPoint^  
14
     EndPoint = gcnew System::Net::IPEndPoint( 
15
                       System::Net::IPAddress::Parse( "90.119.79.255" ), 
16
                       65000   );
17
  UpdSocket->SendTo( TxBuffer, 0, TxBuffer->Length,
18
                     System::Net::Sockets::SocketFlags::None, 
19
                     EndPoint  );
20
}

Das ganze funktionert wie gewünscht. Mich stören allerdings folgende 
Punkte:
Beim SentTo muss ich die Broadcastadresse (des/eines) Netzes direkt 
angeben. Wie kann ich das so machen, das automatisch ein Broadcast (am 
besten über alle verfügbaren Adapter) gesendet wird, ohne das Angeben zu 
müssen? Ein System::Net::IPAddress::Broadcast tut garnichts. Ich habe 
auch schon versucht, das Bind wegzulassen. Aber dann geht das 
BeginReceiveFrom nicht, denn das erwartet ein Bind. Nutze ich nur das 
BeginReceive (ohne From), so erhalte ich beim Empfang keine (gültige) 
IP-Adresse des Absenders.

von bluppdidupp (Gast)


Lesenswert?


von Matthias L. (Gast)


Lesenswert?

Hm.. Das versteh ich aber nicht ganz. Dort steht da, das mit 
GetAllNetworkInterfaces eine Liste erstellen muss und für jeden Adapter 
ein Bind durchführen soll.

Aber beim Bind habe ich doch (bisher) gar keine Zuordnung zum Adapter.
1
Socket^  UpdSocket = gcnew Socket( Sockets::AddressFamily::InterNetwork,
2
                                   System::Net::Sockets::SocketType::Dgram,
3
                                   System::Net::Sockets::ProtocolType::Udp );
4
..
5
UpdSocket->Bind( gcnew System::Net::IPEndPoint ( System::Net::IPAddress::Any, 0 ) );

Dies erfolgt doch erst indirekt beim SendTo durch die IP/Endpoint:
1
IPEndPoint^  EndPoint = gcnew IPEndPoint( IPAddress::Parse( "90.119.79.255" ), TRIF_UDP_PORT );
2
UpdSocket->SendTo( TxBuffer, 0, TxBuffer->Length,
3
                        System::Net::Sockets::SocketFlags::None, 
4
                        EndPoint  );

Kann mir das mal bitte jemand erklären?

von Robert L. (lrlr)


Lesenswert?

>Kann mir das mal bitte jemand erklären?

vielleicht wollte er dir sagen, dass dein Wunsch nicht erfüllbar ist, 
und du dir die jeweiligen Broadcast Adressen selber suchen musst.. und 
für jeden Adapter separat eine Broadcast Nachricht schicken musst ??



OT: was u.U. auch nicht wirklich schlau ist, weil sich vielleicht der 
ENDUSER aussuchen möchte welche(n) Adapter er verwenden will

von bluppdidupp (Gast)


Lesenswert?

Matthias Lipinsky schrieb:
> Aber beim Bind habe ich doch (bisher) gar keine Zuordnung zum Adapter.

Dem Thread auf bytes.com nach, hätte ich vermutet das genau dass das 
Problem ist und man vermutlich pro Interface binden müsste.
1
UdpSocket1->bind(IpVonInterface1);
2
UdpSocket2->bind(IpVonInterface2);
3
...
4
5
UdpSocket1->sendTo(IPAddress.Broadcast, port); // Broadcast geht über IF1 raus
6
UdpSocket2->sendTo(IPAddress.Broadcast, port); // Broadcast geht über IF2 raus

...andererseits sagt die Doku zum WinAPI-send() einfach:
1
If the address pointed to by the to parameter contains the INADDR_BROADCAST address and intended port, then the broadcast will be sent out on all interfaces to that port.
INADDR_BROADCAST müsste äquivalent zu IPAddress.Broadcast sein.
Und demnach müsste es eigentlich reichen wenn
IPAddress::Parse( "90.119.79.255" )
durch IPAddress.Broacast / 255.255.255.255 ausgetauscht wird.

von Matthias L. (Gast)


Lesenswert?

Hoi. Danke für die Infos.  Ich habs jetzt so gemacht:
1
List<System::String^>^    AddrList      = gcnew List<System::String^>();
2
array<NetworkInterface^>^ AllInterfaces = NetworkInterface::GetAllNetworkInterfaces();
3
4
for each ( NetworkInterface^  Adapter in AllInterfaces )
5
{
6
  if ( Adapter->NetworkInterfaceType != NetworkInterfaceType::Ethernet ) continue;
7
  //---------------------------------------------------------------
8
  IPInterfaceProperties^                   IpProp     = Adapter->GetIPProperties();
9
  UnicastIPAddressInformationCollection^   IpAddrInfo = IpProp->UnicastAddresses;
10
  //---------------------------------------------------------------
11
  for each ( NetworkInformation::UnicastIPAddressInformation ^IpAddr in IpAddrInfo )
12
  {
13
    if ( IpAddr->IPv4Mask->ToString() == "0.0.0.0" )  continue;
14
    array<System::Byte>^  AddrBytes = IpAddr->Address->GetAddressBytes();
15
    array<System::Byte>^  MaskBytes = IpAddr->IPv4Mask->GetAddressBytes();
16
    System::String^        BCastAddr = gcnew System::String( L"" );
17
    System::String^        Divider   = gcnew System::String( L"" );
18
    System::Byte           Idx       = 0;
19
    while ( Idx < AddrBytes->Length )
20
    {
21
      System::Byte   Value = AddrBytes[Idx] | ~MaskBytes[Idx];
22
      BCastAddr += Divider;
23
      BCastAddr += Value.ToString();
24
      Divider = L".";
25
      Idx++;
26
    }
27
    AddrList->Add( BCastAddr );
28
  }
29
}
30
AddrList->Count.ToString();  // Liste an Broadcast-Adressen
31
32
...
33
34
for each ( System::String^ BCast in AddrList )
35
{
36
  IPEndPoint^  EndPoint = gcnew System::Net::IPEndPoint(IPAddress::Parse( BCast ), 65000 );
37
  UpdSocket->SendTo( TxBuffer, 0, TxBuffer->Length,
38
                     System::Net::Sockets::SocketFlags::None, 
39
                     EndPoint  );
40
}

Laut Drahthai wird auf beiden (hier) aktiven LAN-Adaptern jetzt ein 
Broadcast versendet.

Gruss

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.