C#UDPClient接受任何IP地址

时间:2016-06-07 09:11:04

标签: c# network-programming udp hole-punching

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

  1. 对等1连接到服务器
  2. 服务器备注IP地址和端口
  3. Peer 2连接到服务器并获取Peer 1详细信息
  4. 对等2连接到对等1
  5. 我目前所拥有的是Peer 1连接到端口8924上的服务器,服务器将远程IP地址和端口详细信息写入SQL数据库。对等体2连接到服务器并请求细节,然后对等体2使用获得的细节创建新的UDPClient和IPEndpoint。到目前为止,一切似乎都有效,但是当Peer 2向对等1发送数据时,没有任何东西到来。

    连接Peer 1没有问题 - >服务器,服务器 - >对等1,对等2 - >服务器,服务器 - >同行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);
            }
        }
    

1 个答案:

答案 0 :(得分:0)

@user_ABCD - 事实证明你是对的。如果我使用套接字而不是UDPCLient,我可以" SendTo(EndPoint)"没有绑定,这允许我更改下一次发送的IP地址/端口,并且所有工作都应该如此。

感谢。