teratail header banner
teratail header banner
質問するログイン新規登録

質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.30%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

2回答

2613閲覧

C#で作成したマルチキャストデータ受信プログラムがWindows10、Windows11では、受信しない。

nobysanz

総合スコア42

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2023/11/01 22:57

0

0

実現したいこと

  • Win10、Win11で、マルチキャストデータを受信したい。(プログラムはC#で作成)

前提

C#(.NET Framework4,Visulal Studio2019)で、マルチキャスト送信、受信プログラムを作成しました。

発生している問題・エラーメッセージ

Win7では、作成したプログラムにて送受信できたのですが、Win10、Win11では、受信ができません。

エラーメッセージは発生していません。

該当のソースコード

■マルチキャスト受信プログラム
・コマンドプロンプト実行
・実行ファイル名 multicastReceiveMonitor.exe
・実行方法 multicastReceiveMonitor.exe [マルチキャストIPアドレス] [ポート番号]

C#

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5using System.Net; 6using System.Net.Sockets; 7using System.IO; 8 9namespace multicastReceiveMonitor 10{ 11 class Program 12 { 13 private const int MCADLL_PRINT_DUMP_LENGTH = 16; 14 static void Main(string[] args) 15 { 16 // 初期値設定 17 int port = 12345; // 送信者と同じポートを使用 18 string multicastAddress = "239.0.0.1"; // 送信者と同じマルチキャストアドレス 19 20 if(args.Length == 2) 21 { 22 try 23 { 24 port = int.Parse(args[1]); 25 } 26 catch (Exception e) 27 { 28 Console.WriteLine("パラメータの形式が誤っています。- {0}", args[1]); 29 Console.WriteLine("multicastReceiveMonitor.exe [マルチキャストIPアドレス] [ポート番号]"); 30 Console.WriteLine("{0}", e.Message); 31 return; 32 } 33 multicastAddress = args[0]; 34 } 35 else 36 { 37 Console.WriteLine("引数が足りません。"); 38 Console.WriteLine("multicastReceiveMonitor.exe [マルチキャストIPアドレス] [ポート番号]"); 39 return; 40 } 41 42 try 43 { 44 using (UdpClient client = new UdpClient()) 45 { 46 47 client.ExclusiveAddressUse = false; 48 client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 49 IPEndPoint localEp = new IPEndPoint(IPAddress.Any, port); 50 client.Client.Bind(localEp); 51 52 // マルチキャストグループに参加 53 client.JoinMulticastGroup(IPAddress.Parse(multicastAddress)); 54 Console.WriteLine($"マルチキャストグループ {multicastAddress}:{port}に参加しました。"); 55 while(true) 56 { 57 // マルチキャストメッセージを受信 58 IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, port); 59 byte[] data = client.Receive(ref remoteEndPoint); 60 StringBuilder sb = new StringBuilder(); 61 62 // 受信データをダンプ形式で表示 63 DateTime t = DateTime.Now; 64 sb.Append(String.Format("■RECV■ {0:yyyy/MM/dd HH:mm:ss.fff}\n", t)); 65 sb.Append(String.Format("{0}\n", Dump(data))); 66 Console.WriteLine(sb.ToString()); 67 68 // 受信データをファイルへ出力 69 string filePath = "multicastReceiveMonitor.log"; 70 using (StreamWriter writer = new StreamWriter(filePath, true)) { 71 writer.WriteLine(sb.ToString()); 72 } 73 } 74 } 75 } 76 catch (Exception e) 77 { 78 Console.WriteLine($"エラー: {e.Message}"); 79 } 80 } 81 82 #region (-)ダンプ出力 83 static private string Dump(byte[] data) 84 { 85 StringBuilder Message = new StringBuilder(); 86 87 byte[] Dump = new byte[MCADLL_PRINT_DUMP_LENGTH]; 88 int Line = (data.Length + MCADLL_PRINT_DUMP_LENGTH - 1) / MCADLL_PRINT_DUMP_LENGTH; 89 90 for (int i = 0; i < Line; i++) 91 { 92 for (int j = 0; j < MCADLL_PRINT_DUMP_LENGTH; j++) 93 { 94 int Index = i * MCADLL_PRINT_DUMP_LENGTH + j; 95 96 if (Index < data.Length) 97 { 98 Dump[j] = data[Index]; 99 } 100 else 101 { 102 Dump[j] = 0x00; 103 } 104 } 105 106 Message.Append(BitConverter.ToString(Dump, 0, MCADLL_PRINT_DUMP_LENGTH)); 107 Message.Append("\r\n"); 108 } 109 110 return Message.ToString(); 111 } 112 #endregion 113 114 } 115} 116

■マルチキャスト送信プログラム
・コマンドプロンプト実行
・実行ファイル名 multicastSend.exe
・実行方法 multicastSend.exe [マルチキャストIPアドレス] [ポート番号] [ローカルIPアドレス] [送信データファイル名]

C#

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5using System.IO; 6using System.Net; 7using System.Net.Sockets; 8 9namespace multicastSend 10{ 11 class Program 12 { 13 private const int MCADLL_PRINT_DUMP_LENGTH = 16; 14 static void Main(string[] args) 15 { 16 // 初期化 17 int port = 12345; 18 string multicastAddress = "239.0.0.1"; 19 string localAddress = "239.0.0.1"; 20 21 if (args.Length == 4) 22 { 23 try 24 { 25 port = int.Parse(args[1]); 26 } 27 catch (Exception e) 28 { 29 Console.WriteLine("パラメータの形式が誤っています。- {0}", args[1]); 30 Console.WriteLine("multicastSend.exe [マルチキャストIPアドレス] [ポート番号] [ローカルIPアドレス] [送信データファイル名]"); 31 Console.WriteLine("{0}", e.Message); 32 Environment.Exit(-1); 33 } 34 multicastAddress = args[0]; 35 localAddress = args[2]; 36 37 // ファイル存在チェック 38 if (!File.Exists(args[3])) 39 { 40 Console.WriteLine("送信データファイルが存在しません。{0}", args[2]); 41 Environment.Exit(-1); 42 } 43 } 44 else 45 { 46 Console.WriteLine("引数が足りません。"); 47 Console.WriteLine("multicastSend.exe [マルチキャストIPアドレス] [ポート番号] [ローカルIPアドレス] [送信データファイル名]"); 48 Environment.Exit(-1); 49 } 50 51 Console.WriteLine("マルチキャストグループ [{0}:{1}]", multicastAddress, port); 52 Console.WriteLine("送信NIC [{0}]", localAddress); 53 Console.WriteLine("送信ファイル [{0}]", args[3]); 54 55 string packet_data = ""; // ダンプテキスト 56 List<byte> arData = new List<byte>(); // バイナリデータ 57 58 arData.Clear(); 59 using (StreamReader sr = new StreamReader(args[3], Encoding.GetEncoding("UTF-8"))) 60 { 61 while ((packet_data = sr.ReadLine()) != null) 62 { 63 string[] arPacket_data = packet_data.Split('-'); 64 if (arPacket_data[0].Length == 2) 65 { 66 foreach (string wk_hex in arPacket_data) 67 { 68 string hex = wk_hex.Trim(); 69 arData.Add((byte)Convert.ToInt16(hex, 16)); 70 } 71 } 72 } 73 } 74 75 byte[] sendData = arData.ToArray(); 76 77 IPAddress multicastIP = IPAddress.Parse(multicastAddress); 78 int multicastPort = port; 79 80 try 81 { 82 IPAddress localIPAddress = IPAddress.Parse(localAddress); 83 using (UdpClient udpClient = new UdpClient(new IPEndPoint(localIPAddress, 0))) 84 { 85 IPEndPoint endPoint = new IPEndPoint(multicastIP, multicastPort); 86 udpClient.Send(sendData, sendData.Length, endPoint); 87 88 StringBuilder sb = new StringBuilder(); 89 DateTime t = DateTime.Now; 90 sb.Append(String.Format("■SEND■ {0:yyyy/MM/dd HH:mm:ss.fff}\n", t)); 91 sb.Append(String.Format("{0}\n", Dump(sendData))); 92 Console.WriteLine(sb.ToString()); 93 94 string filePath = "multicastSend.log"; 95 using (StreamWriter writer = new StreamWriter(filePath, true)) 96 { 97 writer.WriteLine(sb.ToString()); 98 } 99 100 } 101 Environment.Exit(0); 102 } 103 catch (SocketException exp) 104 { 105 Console.WriteLine("UdpSender.SendData(): {0}\r\nStack Trace: {1}", exp.Message, exp.StackTrace); 106 } 107 Environment.Exit(-1); 108 } 109 110 private static string Dump(byte[] data) 111 { 112 StringBuilder Message = new StringBuilder(); 113 114 byte[] Dump = new byte[MCADLL_PRINT_DUMP_LENGTH]; 115 int Line = (data.Length + MCADLL_PRINT_DUMP_LENGTH - 1) / MCADLL_PRINT_DUMP_LENGTH; 116 117 for (int i = 0; i < Line; i++) 118 { 119 for (int j = 0; j < MCADLL_PRINT_DUMP_LENGTH; j++) 120 { 121 int Index = i * MCADLL_PRINT_DUMP_LENGTH + j; 122 123 if (Index < data.Length) 124 { 125 Dump[j] = data[Index]; 126 } 127 else 128 { 129 Dump[j] = 0x00; 130 } 131 } 132 133 Message.Append(BitConverter.ToString(Dump, 0, MCADLL_PRINT_DUMP_LENGTH)); 134 Message.Append("\r\n"); 135 } 136 137 return Message.ToString(); 138 } 139 140 /// <summary> 141 /// INT型からBYTEへ変換 142 /// </summary> 143 /// <param name="station_id"></param> 144 /// <returns></returns> 145 private byte[] cvtIntToByte(int station_id) 146 { 147 byte[] byteArray; 148 byteArray = BitConverter.GetBytes(station_id); 149 150 return byteArray; 151 } 152 } 153} 154

■送信データファイル

data.txt

101-02-03-04

試したこと

  • Win11からデータ送信して、Win7でデータ受信OK。
  • Win7で、送信プログラム、受信プログラムを動作して、送受信OK。
  • Win7からデータ送信し、Win10でデータ受信NG。
  • Win7からデータ送信し、Win11でデータ受信NG。
  • Win11のWireSharkにて、マルチキャストのパケットが届いているのを確認しました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hqf00342

2023/11/01 23:27 編集

Windows10/11のファイアウォールで受信プログラムは許可されていますか?
nobysanz

2023/11/02 00:09 編集

コメントありがとうございます。 受信プログラムは許可しております。 ファイアウォールを無効にしても、受信できませんでした。 受信できないPCにて、Firesharkのパケットキャプチャできるため、ファイアウォールでブロックされていないと考えます。
dodox86

2023/11/02 00:16

対象プログラムの権限の問題かもしれません。管理者権限で動作させて試してみるとか、或いはイベントログに何かヒントとなるログが出力されているかもしれません。
nobysanz

2023/11/02 01:12

コメントありがとうございます。 コマンドプロンプトを管理者権限で実行してみました。結果はNGです。 イベントログにも、マルチキャスト通信に関するエラーは発生しておりません。
guest

回答2

0

NICが1枚しかないWin10をVirtualBoxで作るとご提示のプログラムでも受信できたので
おそらくNIC(ネットワークインターフェースカード)が複数ある状態で、受信しようとすると
どちらのNICにBindするか明示しないといけないようですね。

csharp

1int port = 12345; 2IPAddress mcastAddr = IPAddress.Parse("239.0.0.1"); 3IPAddress localIPAddr = IPAddress.Parse("受信したいNICのIPアドレス"); 4 5try 6{ 7 var socket = new Socket(AddressFamily.InterNetwork, 8 SocketType.Dgram, 9 ProtocolType.Udp); 10 11 EndPoint localEP = (EndPoint)new IPEndPoint(localIPAddr, port); 12 socket.Bind(localEP); 13 14 var mcastOption = new MulticastOption(mcastAddr, localIPAddr); 15 socket.SetSocketOption(SocketOptionLevel.IP, 16 SocketOptionName.AddMembership, 17 mcastOption); 18 19 IPEndPoint groupEP = new IPEndPoint(mcastAddr, port); 20 EndPoint remoteEP = (EndPoint)new IPEndPoint(IPAddress.Any, 0); 21 byte[] bytes = new Byte[100]; 22 23 while (true) 24 { 25 Console.WriteLine("Waiting for multicast packets......."); 26 socket.ReceiveFrom(bytes, ref remoteEP); 27 } 28} 29catch (Exception e) 30{ 31}

MulticastOption クラス
https://learn.microsoft.com/ja-jp/dotnet/api/system.net.sockets.multicastoption?view=net-7.0

投稿2023/11/02 02:37

hqf00342

総合スコア396

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hqf00342

2023/11/02 02:42

can110さんとほとんど被ってますね・・。 MulticastOptionのlocalIPの有無だけ違うようなのでチェックしてみてください。
nobysanz

2023/11/06 11:07

回答ありがとうございます。 参考プログラムを動かして確認してみます!
guest

0

Claudeの回答

この問題の原因は、Windows 10のマルチキャスト受信の仕様変更が関係していると考えられます。

Windows 10では、マルチキャスト受信用のソケットを明示的にマルチキャストグループに加入させる必要があるのに対し、Windows 7では自動的に加入されていたためと思われます。
したがって、Windows 10の受信プログラムではソケットオプションを使用してマルチキャストグループに明示的に加入する処理を追加する必要があるでしょう。

具体的には、SocketのSetSocketOptionメソッドを使用してIP_ADD_MEMBERSHIPオプションを設定することで、マルチキャストグループに加入できるはずです。

この設定を受信プログラムのソケット生成時に追加することで、Windows 10でも正常にマルチキャストを受信できるようになると考えられます。

C#

1// マルチキャストグループのアドレス 2IPAddress multicastAddress = IPAddress.Parse("239.255.0.1"); 3 4// UDPソケットの作成 5Socket receiverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 6 7// マルチキャストグループへの加入 8receiverSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(multicastAddress)); 9 10// ポートをバインド 11receiverSocket.Bind(new IPEndPoint(IPAddress.Any, 5000)); 12 13// データの受信 14// ... 15 16// 使用後のソケットのクローズ 17receiverSocket.Close();

しかし私の受信プログラムではUdpClientクラスのJoinMulticastGroupを利用しています。よって_マルチキャストグループへの加入はできていると認識しています。他に考えられる原因はありますか?_

はい、UdpClientのJoinMulticastGroupを使用しているのであれば、マルチキャストグループへの加入はできていますね。

そうすると、考えられる原因は以下のようなことがあると思います。

  • ファイアウォールの設定を確認する

    • Windowsファイアウォールで、UdpClientのポートがブロックされている可能性
  • マルチキャストのTTL設定を確認する

    • ルーターを跨いで通信する場合、TTLが小さすぎるとパケットが届かない可能性
  • ネットワークアダプタの設定を確認する

    • アダプタのプロパティから、IGMP versionが3に設定されているかを確認
  • Wireshark等でパケットキャプチャをする

    • パケットが本当に受信PCに届いているかを確認する
  • 複数のネットワークインタフェースがある場合のバインド設定

    • 正しいインタフェースにバインドされているかを確認

などが考えられます。一つずつ確認していけば、原因が特定できるはずです。
UdpClientの使用方法としては問題ないと思われるので、他の要因を調べてみてください。

投稿2023/11/02 01:52

編集2023/11/02 02:44
can110

総合スコア38352

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nobysanz

2023/11/02 02:38 編集

回答ありがとうございます。 Windows10は明示的に、マルチキャストグループに参加させる必要があるのですね。 ご提供いただきました、ソースにて確認しましたが、受信NGでした。 当方の受信プログラムでは、UdpClientクラスのJoinMulticastGroupメソッドを実行することで マルチキャストグループに参加している認識でした。 Windows10では、当該メソッドは有効でないのかもしれません。 WireSharkで受信パケットが確認できて、プログラムに受信されない状況です。
can110

2023/11/02 02:47

JoinMulticastGroupメソッドを見落としてました。 であればこちらでの動作は未検証ですがコードにはとくだん問題ないと思います。 追記で尋ねてみましたが、あとはNIC設定くらいでしょうか。 でもそれならWireShark結果と矛盾するのかな?
nobysanz

2023/11/02 04:01

コメントありがとうございます。 NIC設定確認してみます。
nobysanz

2023/11/06 11:10

NICの設定にマルチキャスト受信に関する項目はありませんでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問