C# UDPClient 接受任何 IP 地址

Posted

技术标签:

【中文标题】C# UDPClient 接受任何 IP 地址【英文标题】:C# UDPClient accept any IP address 【发布时间】:2016-10-07 02:30:03 【问题描述】:

我正在尝试用 C# 编写一个 3 路 UDP 打孔应用程序。根据我的阅读,步骤如下。

    Peer 1 连接到服务器 服务器备注 IP 地址和端口 Peer 2 连接到服务器并获取 Peer 1 详细信息 Peer 2 连接到 Peer 1

我现在拥有的是 Peer 1 正在连接到端口 8924 上的服务器,服务器将远程 IP 地址和端口详细信息写入 SQL 数据库。 Peer 2 连接到服务器并请求详细信息,然后 Peer 2 使用获得的详细信息创建一个新的 UDPClient 和 IPEndpoint。到目前为止一切似乎都正常,但是当 Peer 2 向 Peer 1 发送数据时,什么都没有到达。

连接 Peer 1 -> Server, Server -> Peer 1, Peer 2 -> Server, Server -> Peer 2 没有问题。

在我看来,Peer 1 似乎不会接受来自另一个 IP 地址的消息,而不是服务器。

下面的代码相当基本,但可能会告诉我哪里出错了。如果有人能帮忙,我将不胜感激。

同行 1

static void Main(string[] args)
    
        int command = 0;
        Random r = new Random();
        while (true)
        
            UdpClient client = new UdpClient();
            IPEndPoint serverEndpoint = new IPEndPoint(IPAddress.Parse("xxx.xxx.xxx.xxx"), 8924);
            client.Connect(serverEndpoint);
            client.Send(BitConverter.GetBytes(command), 1);
            Task.Run(() => 
                byte[] data = client.Receive(ref serverEndpoint);
                Console.WriteLine(ASCIIEncoding.ASCII.GetString(data));
                Console.ReadLine();
            );
            Console.WriteLine("sleep");
            Thread.Sleep(30000);
            Console.WriteLine("resume");

        

    

同行 2

static void Main(string[] args)
    
        while (true)
        
            Console.WriteLine("press enter to start");
            Console.ReadLine();
            UdpClient getDetailsClient = new UdpClient();
            IPEndPoint getDetailsEndpoint = new IPEndPoint(IPAddress.Parse("xxx.xxx.xxx.xxx"), 8924);
            getDetailsClient.Connect(getDetailsEndpoint);
            getDetailsClient.Send(BitConverter.GetBytes(1), 1);
            byte[] details = getDetailsClient.Receive(ref getDetailsEndpoint);
            byte[] bIp = new byte[15];
            int port = BitConverter.ToInt32(details, 0);
            Array.Copy(details, 4, bIp, 0, 15);
            string Ip = ASCIIEncoding.ASCII.GetString(bIp).Trim();
            Console.WriteLine($"Address: Ip \tPort: port");
            UdpClient peerClient = new UdpClient();
            IPEndPoint endpointClient = new IPEndPoint(IPAddress.Parse(Ip), port);
            peerClient.Connect(endpointClient);
            peerClient.Send(ASCIIEncoding.ASCII.GetBytes("test"), 4);
            Console.ReadLine();
        

    

服务器

static void Main(string[] args)
    
        int port =  8924;
        IPEndPoint remote = new IPEndPoint(IPAddress.Any, port);
        byte command;

        UdpClient server = new UdpClient(port);
        while(true)
        
            //Wait on connection from client                
            var data = server.Receive(ref remote);
            //get command
            command = data[0];
            switch(command)
            
                case (byte)0:
                    updateDatabase(ref server, ref remote);
                    break;
                case (byte)1:
                    readDatabase(ref server, ref remote);
                    break;
                default:
                    break;
            

        

    

    private static void updateDatabase(ref UdpClient server, ref IPEndPoint remote)
    
        Console.WriteLine("Write Command");
        using (dbDataContext db = new dbDataContext())
        
            ConnectionTB tb = db.ConnectionTBs
                .Where(t => t.UniqueIdentifier.Trim().Equals("123456789"))
                .Select(t => t)
                .FirstOrDefault();
            tb.Port = remote.Port;
            tb.IPAddress = remote.Address.ToString();
            tb.LastPing = DateTime.Now;
            db.SubmitChanges();
            server.Send(ASCIIEncoding.ASCII.GetBytes(remote.Address.ToString().PadRight(15)),15,remote);
        
    

    private static void readDatabase(ref UdpClient server, ref IPEndPoint remote)
    
        Console.WriteLine("Read Command");
        using (dbDataContext db = new dbDataContext())
        
            ConnectionTB  p = db.ConnectionTBs
                .Where(c => c.UniqueIdentifier.Trim().Equals("123456789"))
                .Select(c => c)
                .FirstOrDefault();

            int port = p.Port.Value;
            string ip = p.IPAddress.Trim();
            byte[] data = new byte[19];
            byte[] bPort = BitConverter.GetBytes(port);
            byte[] bIp = ASCIIEncoding.ASCII.GetBytes(p.IPAddress.PadRight(15));

            Array.Copy(bPort, 0, data, 0, 4);
            Array.Copy(bIp, 0, data, 4, 15);
            server.Send(data, 19, remote);
        
    

【问题讨论】:

我从来没有见过,所以我会问。 IPAddress.Parse("xxx.xxx.xxx.xxx") 在做什么?您实际上如何向端点提供 IP 地址?我相信问题在于您使用连接的 udp 套接字这一事实。 @user_ABCD - 它从标准 IP 地址格式的字符串表示形式创建一个 IPAddress 对象,例如“192.168.1.1”。我使用“x”删除了我的服务器的实际 IP 地址。 哈哈,我傻了。我相信您最好的选择是将 ip & port 直接传递给 connect 调用。然后在您的客户端之前创建端点。接收呼叫并将 IPAddress.Any 传递给它。 【参考方案1】:

@user_ABCD - 事实证明你是对的。如果我使用 Sockets 而不是 UDPCLient,我可以“SendTo(EndPoint)”而不进行绑定,这使我可以更改下一次发送的 IP 地址/端口,并且一切正常。

谢谢。

【讨论】:

以上是关于C# UDPClient 接受任何 IP 地址的主要内容,如果未能解决你的问题,请参考以下文章

如何从任何 ip 和任何端口接收 UDP 数据包?

如何使 UdpClient 非阻塞

C#:UdpClient 很快调用 close() 时不发送数据

我可以在 C# 中为 UdpClient 设置超时吗?

C# UdpClient 设置超时时间

如何使用 C# UdpClient 发送大数据?