侧边栏壁纸
  • 累计撰写 74 篇文章
  • 累计创建 45 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

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

码峰
2022-09-19 / 0 评论 / 0 点赞 / 116 阅读 / 732 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-09-20,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

需求描述

在设备搜索相关的协议中,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可以正常实现双向通讯。

0

评论区