雷达智富

首页 > 内容 > 程序笔记 > 正文

程序笔记

在C#中实现局域网中不在同一子网的两个机器双向UDP组播

2024-08-08 30

需求描述

在设备搜索相关的协议中,UDP被广泛使用,当不知道对方真实IP地址,并且可能两台机器不在同一个子网下,此时就不能直接使用UDP通讯,换句话说,不在相同子网下的两台机器(例如如子网掩码为255.255.255.0,机器A:192.168.11.11,机器B:192.168.1.101),普通的TCP或UDP发送都无法直接到达对方,此时就需要使用UDP的组播模式。接下来就介绍一下在C#中双向组播的实现。

实现代码

Server端

使用UDP组播,并没有服务端和客户端之分,只是在具体应用中,根据应用具体的逻辑,可以将一端的业务逻辑划分为服务端,另一端为客户端。因此,这里Server端的代码如下:

    Socket udpServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    udpServerSocket.ReceiveTimeout = 1000;
    udpServerSocket.MulticastLoopback = false;  //禁用本地组播回环,否则自己发送的组播消息自己也会收到,形成死循环
    udpServerSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership,   //加入组播
                                                            new MulticastOption(IPAddress.Parse(224.0.0.22), IPAddress.Any));

    udpServerSocket.Bind(new IPEndPoint(IPAddress.Any, 18000));
            
    byte[] buf = new byte[1024];
            
    while (true)
    {
        EndPoint endpoint = new IPEndPoint(IPAddress.Any, 0);
        int recvCount = udpServerSocket.ReceiveFrom(buf, ref endpoint);
        Console.WriteLine(Receive {0} bytes from {1}., recvCount, endpoint);
        Console.WriteLine(Receive message: {0}, Encoding.Default.GetString(buf));
        
        var txEdp = new IPEndPoint(IPAddress.Parse(224.0.0.22), 18000);
        udpServerSocket.SendTo(Encoding.Default.GetBytes(Hi!), txEdp);
       Console.WriteLine(Send \Hi!\ to {0}., txEdp);
    }

Client端

客户端的代码如下:

    Socket UDPSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    UDPSocket.ReceiveTimeout = 10000;
    UDPSocket.ExclusiveAddressUse = false;
    UDPSocket.MulticastLoopback = false;
    UDPSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    UDPSocket.Bind(new IPEndPoint(IPAddress.Any, 18000));
    UDPSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse(224.0.0.22)));

    var txEdp = new IPEndPoint(IPAddress.Parse(224.0.0.22), 18000);
    byte[] buf = new byte[1024];
    while (true)
    {
        UDPSocket.SendTo(Encoding.Default.GetBytes(Hello!), txEdp);
        Console.WriteLine(Send \Hello!\ to {0}., txEdp);

        EndPoint endpoint = new IPEndPoint(IPAddress.Any, 0);
        int recvCount = UDPSocket.ReceiveFrom(buf, ref endpoint);

        Console.WriteLine(Receive {0} bytes from {1}., recvCount, endpoint);
        Console.WriteLine(Receive message: {0}, Encoding.Default.GetString(buf));
        Thread.Sleep(1000);
    }

运行结果

运行环境:
机器A:Ubuntu虚拟机,桥接网卡,IP地址为静态指定:192.168.11.11
机器B:Windows的机器,与机器A桥接网卡连接同一交换机,IP机制为动态获取:192.168.1.101
以上两个机器,如果是简单的TCP或UDP是无法通讯的,使用以上示例代码运行结果如下:

  • 服务端:
Receive 6 bytes from 192.168.1.101:18061.
Receive message: Hello!
Send Hi! to 224.0.0.22:18000.
  • 客户端:
Send Hello! to 224.0.0.61:18000.
Receive 3 bytes from 192.168.11.11:18000.
Receive message: Hi! 
......

从运行结果可以看到,机器A和机器B可以正常实现双向通讯。

更新于:1个月前
赞一波!

文章评论

全部评论