UDP端口打孔C#

UDP端口打孔C#,udp,hole-punching,Udp,Hole Punching,我试图让NAT后面的两个客户端使用端口转发工作的服务器相互通信,我的场景: Server start listering on port 45000 for Client_A connection; Server Start listering on port 45001 for Client_B connection; Client_A connect to server on port 45000 and send hello message; Client_B connect to

我试图让NAT后面的两个客户端使用端口转发工作的服务器相互通信,我的场景:

Server start listering on port 45000 for Client_A connection;

Server Start listering on port 45001 for Client_B connection;

Client_A connect to server on port 45000 and send hello message;

Client_B connect to server on port 45001 and send hello message;

Server Receive hello message from Client_B and send message with Client_B external port (ex 56000) to Client_B;

Client_B receive external port and start listering on port 56000;

Server Receive hello message from Client_A and send message with Client_B IP and port to Client_A;

Client_A receive IP and Port of Client_B;

Client_A connect to Client_B and send hello message
问题:

Client_B does not receive message from Client_A;
        static int server_A_Port = 45000;
        static int server_B_Port = 45001;

        static UdpClient server_A;
        static UdpClient server_B;

        static bool client_B_Connected = false;

        static string client_A_Ip = "";
        static string client_B_Ip = "";
        static int client_A_Port = 0;
        static int client_B_Port = 0;

        static Thread Server_A_Thread = new Thread(Start_Server_A);
        static Thread Server_B_Thread = new Thread(Start_Server_B);

        static void Main(string[] args)
        {
            Server_A_Thread.Start();
            Server_B_Thread.Start();
        }
        static void Start_Server_A()
        {
            Console.WriteLine("Starting Server_A on port: " + server_A_Port);
            server_A = new UdpClient();
            IPEndPoint client_A_IpEp = new IPEndPoint(IPAddress.Any, server_A_Port);
            server_A.Client.Bind(client_A_IpEp);

            Console.WriteLine("Server Started. Waiting Client_A Message");
            string c_a = "";
            while (string.IsNullOrEmpty(c_a))
            {
                try
                {
                    c_a = ReceiveMessageFromClient(server_A, ref client_A_IpEp);
                    Console.WriteLine("Message received from Client_A: " + c_a);
                    client_A_Ip = ((IPEndPoint)client_A_IpEp).Address.ToString();
                    client_A_Port = ((IPEndPoint)client_A_IpEp).Port;
                    server_A.Connect(client_A_IpEp);
                }
                catch(Exception err)
                {
                    Thread.Sleep(1000);
                }
            }

            Console.WriteLine("Waiting Client_B connection");
            bool sended = false;
            while (!sended)
            {
                if(client_B_Connected)
                {
                    Console.WriteLine("Client_B connected, sending Client_B IP and Port to Client_A");
                    SendMessageToClient(server_A, client_B_Ip + ":" + client_B_Port);

                    sended = true;
                    Console.WriteLine("Message Sended to Client_A");
                    break;
                }
                Thread.Sleep(1000);
            }
            Console.ReadLine();
        }

        static void Start_Server_B()
        {
            Console.WriteLine("Starting Server_B on port: " + server_B_Port);
            server_B = new UdpClient();
            IPEndPoint client_B_IpEp = new IPEndPoint(IPAddress.Any, server_B_Port);
            server_B.Client.Bind(client_B_IpEp);

            Console.WriteLine("Server Started. Waiting Client_B Message");
            string c_b = "";
            while (string.IsNullOrEmpty(c_b))
            {
                try
                {
                    c_b = ReceiveMessageFromClient(server_B, ref client_B_IpEp);
                    Console.WriteLine("Message received from Client_B: " + c_b);
                    client_B_Ip = ((IPEndPoint)client_B_IpEp).Address.ToString();
                    client_B_Port = ((IPEndPoint)client_B_IpEp).Port;
                    server_B.Connect(client_B_IpEp);
                    client_B_Connected = true;
                }
                catch (Exception err)
                {
                    Thread.Sleep(1000);
                }
            }
            Console.WriteLine("Sending external Port to Client_B start listering");
            SendMessageToClient(server_B,client_B_Port + "");           
        }

        static void SendMessageToClient(UdpClient client, string message)
        {
            byte[] data = Encoding.GetEncoding(28591).GetBytes(message);
            client.Send(data, data.Length);
        }

        static string ReceiveMessageFromClient(UdpClient client, ref IPEndPoint ep)
        {
            byte[] data = client.Receive(ref ep);
            string receivedString = Encoding.GetEncoding(28591).GetString(data);
            return receivedString;
        }
代码如下:

服务器:

Client_B does not receive message from Client_A;
        static int server_A_Port = 45000;
        static int server_B_Port = 45001;

        static UdpClient server_A;
        static UdpClient server_B;

        static bool client_B_Connected = false;

        static string client_A_Ip = "";
        static string client_B_Ip = "";
        static int client_A_Port = 0;
        static int client_B_Port = 0;

        static Thread Server_A_Thread = new Thread(Start_Server_A);
        static Thread Server_B_Thread = new Thread(Start_Server_B);

        static void Main(string[] args)
        {
            Server_A_Thread.Start();
            Server_B_Thread.Start();
        }
        static void Start_Server_A()
        {
            Console.WriteLine("Starting Server_A on port: " + server_A_Port);
            server_A = new UdpClient();
            IPEndPoint client_A_IpEp = new IPEndPoint(IPAddress.Any, server_A_Port);
            server_A.Client.Bind(client_A_IpEp);

            Console.WriteLine("Server Started. Waiting Client_A Message");
            string c_a = "";
            while (string.IsNullOrEmpty(c_a))
            {
                try
                {
                    c_a = ReceiveMessageFromClient(server_A, ref client_A_IpEp);
                    Console.WriteLine("Message received from Client_A: " + c_a);
                    client_A_Ip = ((IPEndPoint)client_A_IpEp).Address.ToString();
                    client_A_Port = ((IPEndPoint)client_A_IpEp).Port;
                    server_A.Connect(client_A_IpEp);
                }
                catch(Exception err)
                {
                    Thread.Sleep(1000);
                }
            }

            Console.WriteLine("Waiting Client_B connection");
            bool sended = false;
            while (!sended)
            {
                if(client_B_Connected)
                {
                    Console.WriteLine("Client_B connected, sending Client_B IP and Port to Client_A");
                    SendMessageToClient(server_A, client_B_Ip + ":" + client_B_Port);

                    sended = true;
                    Console.WriteLine("Message Sended to Client_A");
                    break;
                }
                Thread.Sleep(1000);
            }
            Console.ReadLine();
        }

        static void Start_Server_B()
        {
            Console.WriteLine("Starting Server_B on port: " + server_B_Port);
            server_B = new UdpClient();
            IPEndPoint client_B_IpEp = new IPEndPoint(IPAddress.Any, server_B_Port);
            server_B.Client.Bind(client_B_IpEp);

            Console.WriteLine("Server Started. Waiting Client_B Message");
            string c_b = "";
            while (string.IsNullOrEmpty(c_b))
            {
                try
                {
                    c_b = ReceiveMessageFromClient(server_B, ref client_B_IpEp);
                    Console.WriteLine("Message received from Client_B: " + c_b);
                    client_B_Ip = ((IPEndPoint)client_B_IpEp).Address.ToString();
                    client_B_Port = ((IPEndPoint)client_B_IpEp).Port;
                    server_B.Connect(client_B_IpEp);
                    client_B_Connected = true;
                }
                catch (Exception err)
                {
                    Thread.Sleep(1000);
                }
            }
            Console.WriteLine("Sending external Port to Client_B start listering");
            SendMessageToClient(server_B,client_B_Port + "");           
        }

        static void SendMessageToClient(UdpClient client, string message)
        {
            byte[] data = Encoding.GetEncoding(28591).GetBytes(message);
            client.Send(data, data.Length);
        }

        static string ReceiveMessageFromClient(UdpClient client, ref IPEndPoint ep)
        {
            byte[] data = client.Receive(ref ep);
            string receivedString = Encoding.GetEncoding(28591).GetString(data);
            return receivedString;
        }
客户_A

static string serverIp = "X.X.X.X";
static int serverPort = 45000;
        static string otherClientIp = "0.0.0.0";
    static int otherClientPort = 0;

    static UdpClient client = new UdpClient();

    static void Main(string[] args)
    {
        Console.WriteLine("Connecting to server...");
        client.Connect(serverIp, serverPort);
        Console.WriteLine("Connected. Sending request message...");
        SendMessageToServer();
        Console.WriteLine("Sended. Waiting response...");
        string s = "";
        while (string.IsNullOrEmpty(s))
        {
            try
            {
                s = ReceiveMessageFromServer();
                Console.WriteLine("Response received from server.");
            }
            catch (Exception err)
            {
                Thread.Sleep(1000);
            }
        }
        string[] otherClientInfo = s.Split(':');
        otherClientIp = otherClientInfo[0];
        otherClientPort = int.Parse(otherClientInfo[1]);
        Console.WriteLine("Other Client info: " + otherClientIp + ":" + otherClientPort);

        Thread.Sleep(2000);
        Console.WriteLine("Connecting to Client_B...");
        client.Connect(otherClientIp, otherClientPort);
        Console.WriteLine("Connected. Sending hello hessage...");
        SendMessageToClient();
        Console.WriteLine("Sended. Waiting response...");

        string c = "";
        while (string.IsNullOrEmpty(c))
        {
            try
            {
                IPEndPoint ep = (IPEndPoint)client.Client.RemoteEndPoint;
                c = ReceiveMessageFromClient(client,ref ep);
                Console.WriteLine("Response received from Client_B.");
                Console.WriteLine("Response: " + c);
                Console.ReadLine();
            }
            catch (Exception err)
            {
                Thread.Sleep(1000);
            }
        }
    }

    static void SendMessageToServer()
    {
        byte[] data = Encoding.GetEncoding(28591).GetBytes("FROM CLIENT TO SERVER");
        client.Send(data, data.Length);
    }
    static void SendMessageToClient()
    {
        byte[] data = Encoding.GetEncoding(28591).GetBytes("FROM CLIENT_A TO CLIENT_B");
        client.Send(data, data.Length);
    }

    static string ReceiveMessageFromServer()
    {
        IPEndPoint serverIpEp = new IPEndPoint(IPAddress.Parse(serverIp), serverPort);
        byte[] data = client.Receive(ref serverIpEp);
        string receivedString = Encoding.GetEncoding(28591).GetString(data);
        return receivedString;
    }
    static string ReceiveMessageFromClient(UdpClient server, ref IPEndPoint ep)
    {
        byte[] data = server.Receive(ref ep);
        string receivedString = Encoding.GetEncoding(28591).GetString(data);
        return receivedString;
    }
客户_B

    static string serverIp = "X.X.X.X";
    static int serverPort = 45001;

    static UdpClient client = new UdpClient();
    static void Main(string[] args)
    {
        Console.WriteLine("Connecting to server...");
        client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
        client.Connect(serverIp, serverPort);
        Console.WriteLine("Connected. Sending request message...");
        SendMessageToServer();
        Console.WriteLine("Sended. Waiting response...");
        string s = "";
        while (string.IsNullOrEmpty(s))
        {
            try
            {
                s = ReceiveMessageFromServer();
                Console.WriteLine("Response received from server.");
            }
            catch (Exception err)
            {
                Thread.Sleep(1000);
            }
        }
        Console.WriteLine("My External Port: " + s);

        //IPEndPoint ep = new IPEndPoint(IPAddress.Any, ((IPEndPoint)client.Client.LocalEndPoint).Port);
        IPEndPoint ep = new IPEndPoint(IPAddress.Any, int.Parse(s));
        Console.WriteLine("Start Binding on Extenal Port: " + ep.Port);
        UdpClient server = new UdpClient();
        server.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
        server.Client.Bind(ep);
        Console.WriteLine("Started. Waiting hello message...");
        string c = "";
        while (string.IsNullOrEmpty(c))
        {
            try
            {
                c = ReceiveMessageFromClient(server, ref ep);
                Console.WriteLine("Response received from Client_A.");
                Console.WriteLine("Response: " + c);
                client.Connect(ep);
                Console.ReadLine();
            }
            catch (Exception err)
            {
            }
        }

        Console.WriteLine("Sending message to Client_A...");
        SendMessageToClient();
        Console.WriteLine("Sended.");
        Console.ReadLine();
        var myRule = FirewallManager.Instance.Rules.SingleOrDefault(r => r.Name == "TEST_RULE");
        FirewallManager.Instance.Rules.Remove(myRule);
    }

    static void SendMessageToServer()
    {
        byte[] data = Encoding.GetEncoding(28591).GetBytes("FROM CLIENT TO SERVER");
        client.Send(data, data.Length);
    }
    static void SendMessageToClient()
    {
        byte[] data = Encoding.GetEncoding(28591).GetBytes("FROM CLIENT_B TO CLIENT_A");
        client.Send(data, data.Length);
    }

    static string ReceiveMessageFromServer()
    {
        IPEndPoint serverIpEp = new IPEndPoint(IPAddress.Parse(serverIp), serverPort);
        byte[] data = client.Receive(ref serverIpEp);
        string receivedString = Encoding.GetEncoding(28591).GetString(data);
        return receivedString;
    }
    static string ReceiveMessageFromClient(UdpClient server, ref IPEndPoint ep)
    {
        byte[] data = server.Receive(ref ep);
        string receivedString = Encoding.GetEncoding(28591).GetString(data);
        return receivedString;
    }
我不知道哪里出了问题,也不知道如何让它发挥作用,我做了很多研究,还没有找到解决办法

对不起,英语不好