13

特定のIPとポートにUDPメッセージを送信する必要があります。

ネットワークカードが3枚あるので、

10.1.x.x
10.2.x.x
10.4.x.x

UDPメッセージを送信すると、1つのネットワークアダプターでのみメッセージを受信して​​います...残りのIPは受信していません。

メッセージの送信中にネットワークアダプタを確認したい。どうやってやるの?


現在、私は以下を使用しています:

IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse(LocalIP), 0);
IPEndPoint targetEndPoint = new IPEndPoint(TargetIP, iTargetPort);
UdpClient sendUdpClient = new UdpClient(localEndPoint);
int numBytesSent = sendUdpClient.Send(CombineHeaderBody, CombineHeaderBody.Length, targetEndPoint);
4

4 に答える 4

18

複数のインターフェイスがある場合、ブロードキャストが常にすべてのインターフェイスに送信されるとは限らないため、これは実際には思ったよりもトリッキーです。これを回避するために、このクラスを作成しました。

public class MyUdpClient : UdpClient
{
   public MyUdpClient() : base()
   {
      //Calls the protected Client property belonging to the UdpClient base class.
      Socket s = this.Client;
      //Uses the Socket returned by Client to set an option that is not available using UdpClient.
      s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
      s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontRoute, 1);
   }

   public MyUdpClient(IPEndPoint ipLocalEndPoint) : base(ipLocalEndPoint)
   {
      //Calls the protected Client property belonging to the UdpClient base class.
      Socket s = this.Client;
      //Uses the Socket returned by Client to set an option that is not available using UdpClient.
      s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
      s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontRoute, 1);
   }

}

次に、UDP パケットをブロードキャストで送信するには、次のようなものを使用します。私は and を使用IPAddress.BroadcastしてMyUdpClientいますが、これはあなたのコードとは異なります。

IPEndPoint  localEndPoint  = new IPEndPoint(IPAddress.Parse(LocalIP), 0);
IPEndPoint  targetEndPoint = new IPEndPoint(IPAddress.Broadcast, iTargetPort);
MyUdpClient sendUdpClient  = new MyUdpClient(localEndPoint);
int numBytesSent = sendUdpClient.Send(CombineHeaderBody, CombineHeaderBody.Length, targetEndPoint);

ipaddressまた、ブロードキャストの代わりに特定のものを使用する場合、ルート テーブルはアドレスに一致するインターフェイスのみを送信することに注意してください。

あなたの例では、ユニキャストが使用されています。LocalIP送信先のローカル インターフェイスの IPに設定する必要があります。3 つのインターフェイスを使用すると、3 つのローカル IP を持つことになり、使用する正しい IP を選択する必要があります。

IPEndPoint  localEndPoint  = new IPEndPoint(IPAddress.Parse(LocalIP), 0);
IPEndPoint  targetEndPoint = new IPEndPoint(TargetIP, iTargetPort);
MyUdpClient sendUdpClient  = new MyUdpClient(localEndPoint);
int numBytesSent = sendUdpClient.Send(CombineHeaderBody, CombineHeaderBody.Length, targetEndPoint);

ルートがオフになっているため、すべてのインターフェイスでルートが表示される可能性がありますが、ユニキャストの場合にこれをテストする必要があります。

送信 IP またはポートを気にしない場合は、次のコードを使用できます。

IPEndPoint  targetEndPoint = new IPEndPoint(TargetIP, iTargetPort);
MyUdpClient sendUdpClient  = new MyUdpClient();
int numBytesSent = sendUdpClient.Send(CombineHeaderBody, CombineHeaderBody.Length, targetEndPoint);

または放送用

IPEndPoint  targetEndPoint = new IPEndPoint(IPAddress.Broadcast, iTargetPort);
MyUdpClient sendUdpClient  = new MyUdpClient();
int numBytesSent = sendUdpClient.Send(CombineHeaderBody, CombineHeaderBody.Length, targetEndPoint);

問題IPAddress.Broadcastは、ゲートウェイを経由しないことです。これを回避するには、リストを作成し、IPAddressesループして送信します。また、制御できないネットワークの問題で送信が失敗する可能性があるため、try/catch ブロックも必要です。

ArrayList ip_addr_acq = new ArrayList();

ip_addr_acq.Add(IPAddress.Parse("10.1.1.1")); // add to list of address to send to

try
{
   foreach (IPAddress curAdd in ip_addr_acq) 
   {
       IPEndPoint  targetEndPoint = new IPEndPoint(curAdd , iTargetPort);
       MyUdpClient sendUdpClient  = new MyUdpClient();
       int numBytesSent = sendUdpClient.Send(CombineHeaderBody, CombineHeaderBody.Length, targetEndPoint);

       Thread.Sleep(40); //small delay between each message
    }
 }
 catch
 {
 // handle any exceptions
 }

編集: 複数のインターフェイスを使用したユニキャストへの上記の変更と、利用可能なネットワークにパケットをユニキャストしようとしている問題も参照してください。

于 2009-07-08T05:11:32.083 に答える
4

各アダプターからUDPブロードキャストを送信することでこの問題を解決しました(バインドを使用):

public static void SNCT_SendBroadcast(out List<MyDevice> DevicesList)
{
DevicesList = new List<MyDevice>();
byte[] data = new byte[2]; //broadcast data
data[0] = 0x0A;
data[1] = 0x60;

IPEndPoint ip = new IPEndPoint(IPAddress.Broadcast, 45000); //braodcast IP address, and corresponding port

NetworkInterface[] nics = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces(); //get all network interfaces of the computer

foreach (NetworkInterface adapter in nics)
{
// Only select interfaces that are Ethernet type and support IPv4 (important to minimize waiting time)
if (adapter.NetworkInterfaceType != NetworkInterfaceType.Ethernet) { continue; }
if (adapter.Supports(NetworkInterfaceComponent.IPv4) == false) { continue; }
try
{
    IPInterfaceProperties adapterProperties = adapter.GetIPProperties();    
    foreach (var ua in adapterProperties.UnicastAddresses)
    {
        if (ua.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
        {
         //SEND BROADCAST IN THE ADAPTER
            //1) Set the socket as UDP Client
            Socket bcSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); //broadcast socket
            //2) Set socker options
            bcSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
            bcSocket.ReceiveTimeout = 200; //receive timout 200ms
            //3) Bind to the current selected adapter
            IPEndPoint myLocalEndPoint = new IPEndPoint(ua.Address, 45000);
            bcSocket.Bind(myLocalEndPoint);
            //4) Send the broadcast data
            bcSocket.SendTo(data, ip);

        //RECEIVE BROADCAST IN THE ADAPTER
            int BUFFER_SIZE_ANSWER = 1024;
            byte[] bufferAnswer = new byte[BUFFER_SIZE_ANSWER];
            do
            {
                try
                {
                    bcSocket.Receive(bufferAnswer);
                    DevicesList.Add(GetMyDevice(bufferAnswer)); //Corresponding functions to get the devices information. Depends on the application.
                }
                catch { break; }

            } while (bcSocket.ReceiveTimeout != 0); //fixed receive timeout for each adapter that supports our broadcast
            bcSocket.Close();
        }
    }
  }
  catch { }
}
return;
}
于 2017-06-19T07:01:46.780 に答える
3

レックスの答えの拡張。これにより、ブロードキャストする IP アドレスをハードコーディングする必要がなくなります。すべてのインターフェイスをループし、それらが稼働しているかどうかを確認し、IPv4 情報があることを確認し、IPv4 アドレスがそれに関連付けられていることを確認します。「データ」変数をブロードキャストしたいデータに変更し、「ターゲット」ポートを必要なものに変更するだけです。小さな欠点は、インターフェイスに複数の IP アドレスが関連付けられている場合、各アドレスからブロードキャストされることです。注: これは、任意の VPN アダプター (ネットワークおよび共有センター/ネットワーク接続経由​​、Win 7+ 検証済み) を介してブロードキャストを送信しようとします。応答を受信したい場合は、すべてのクライアントを保存する必要があります。また、二次クラスは必要ありません。

    foreach( NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces() ) {
        if( ni.OperationalStatus == OperationalStatus.Up && ni.SupportsMulticast && ni.GetIPProperties().GetIPv4Properties() != null ) {
            int id = ni.GetIPProperties().GetIPv4Properties().Index;
            if( NetworkInterface.LoopbackInterfaceIndex != id ) {
                foreach(UnicastIPAddressInformation uip in ni.GetIPProperties().UnicastAddresses ) {
                    if( uip.Address.AddressFamily == AddressFamily.InterNetwork ) {
                        IPEndPoint local = new IPEndPoint(uip.Address.Address, 0);
                        UdpClient udpc = new UdpClient(local);
                        udpc.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
                        udpc.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontRoute, 1);
                        byte[] data = new byte[10]{1,2,3,4,5,6,7,8,9,10};
                        IPEndPoint target = new IPEndPoint(IPAddress.Broadcast, 48888);
                        udpc.Send(data,data.Length, target);
                    }
                }
            }
        }
    }
于 2016-09-25T19:42:36.877 に答える
1

特定のIPアドレスに送信している場合は、ブロードキャストではなくユニキャストです。

于 2009-07-08T04:46:30.637 に答える