internal class PeerMulticastFinder : IDisposable
public PeerMulticastFinder()
MulticastSocket = new Socket(AddressFamily.InterNetwork,
MulticastAddress = IPAddress.Parse("230.138.100.2");
var ipList = GetLocalIpList().ToList();
var message = string.Join(';',ipList);
SendBroadcastMessage(message);
// 先发送再获取消息,这样就不会收到自己发送的消息
ReceivedMessage += (s, e) => { Console.WriteLine($"找到 {e}"); };
private IEnumerable<IPAddress> GetLocalIpList()
var host = Dns.GetHostEntry(Dns.GetHostName());
foreach (var ip in host.AddressList)
if (ip.AddressFamily == AddressFamily.InterNetwork)
/// 224.0.0.0~224.0.0.255为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其它地址供路由协议使用;
/// 224.0.1.0~224.0.1.255是公用组播地址,可以用于Internet;
/// 224.0.2.0~238.255.255.255为用户可用的组播地址(临时组地址),全网范围内有效;
/// 239.0.0.0~239.255.255.255为本地管理组播地址,仅在特定的本地范围内有效。
public IPAddress MulticastAddress { set; get; }
private const int MulticastPort = 15003;
public void StartMulticast()
// 如果首次绑定失败,那么将无法接收,但是可以发送
// Define a MulticastOption object specifying the multicast group
// address and the local IPAddress.
// The multicast group address is the same as the address used by the server.
// 有多个 IP 时,指定本机的 IP 地址,此时可以接收到具体的内容
var multicastOption = new MulticastOption(MulticastAddress, IPAddress.Parse("172.18.134.16"));
MulticastSocket.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.AddMembership,
Console.WriteLine(e.ToString());
Task.Run(ReceiveBroadcastMessages);
public event EventHandler<string> ReceivedMessage;
private void ReceiveBroadcastMessages()
// 接收需要绑定 MulticastPort 端口
var bytes = new byte[MaxByteLength];
EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
var length = MulticastSocket.ReceiveFrom(bytes, ref remoteEndPoint);
OnReceivedMessage(Encoding.UTF8.GetString(bytes, 0, length));
Console.WriteLine(e.ToString());
/// <param name="message"></param>
public void SendBroadcastMessage(string message)
var endPoint = new IPEndPoint(MulticastAddress, MulticastPort);
var byteList = Encoding.UTF8.GetBytes(message);
if (byteList.Length > MaxByteLength)
throw new ArgumentException($"传入 message 转换为 byte 数组长度太长,不能超过{MaxByteLength}字节")
MulticastSocket.SendTo(byteList, endPoint);
Console.WriteLine("\n" + e);
private IPAddress LocalIpAddress { set; get; } = IPAddress.Any;
private Socket MulticastSocket { get; }
private void TryBindSocket()
for (var i = MulticastPort; i < 65530; i++)
EndPoint localEndPoint = new IPEndPoint(LocalIpAddress, i);
MulticastSocket.Bind(localEndPoint);
catch (SocketException e)
private const int MaxByteLength = 1024;
#region IDisposable Support
private bool _disposedValue = false; // 要检测冗余调用
private void Dispose(bool disposing)
MulticastSocket.Dispose();
// 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
GC.SuppressFinalize(this);
private void OnReceivedMessage(string e)
ReceivedMessage?.Invoke(this, e);