如何使用外部 IP 地址访问 UDP 服务器

How to access UDP Server using external IP Address

我有以下 UDP 服务器在端口 11000 上侦听:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;

namespace UDPServer
{
    class Program
    {
        static byte[] dataToSend = new byte[] { 1, 2, 3, 4, 5 };

    // get the ip and port number where the client will be listening on
    static IPEndPoint GetClientInfo()
    {
        // wait for client to send data
        using (UdpClient listener = new UdpClient(11000))
        {
            IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, 11000);
            byte[] receive_byte_array = listener.Receive(ref groupEP);

            return groupEP;
        }
    }

    static void Main(string[] args)
    {
        var info = GetClientInfo(); // get client info

        /* NOW THAT WE HAVE THE INFO FROM THE CLIENT WE ARE GONG TO SEND
           DATA TO IT FROM SCRATCH!. NOTE THE CLIENT IS BEHIND A NAT AND
           WE WILL STILL BE ABLE TO SEND PACKAGES TO IT
        */

        // create a new client. this client will be created on a 
        // different computer when I do readl udp punch holing
        UdpClient newClient = ConstructUdpClient(info);

        // send data
        newClient.Send(dataToSend, dataToSend.Length);
    }

    // Construct a socket with the info received from the client
    static UdpClient ConstructUdpClient(IPEndPoint clientInfo)
    {
        var ip = clientInfo.Address.ToString();
        var port = clientInfo.Port;

        // this is the part I was missing!!!!
        // the local end point must match. this should be the ip this computer is listening on
        // and also the port            
        UdpClient client = new UdpClient(new IPEndPoint(IPAddress.Any, 11000));

        // lastly we are missing to set the end points. (ip and port client is listening on)

        // the connect method sets the remote endpoints
        client.Connect(ip, port);

        return client;
    }
}

我还在我的路由器中打开了一个端口,因此当从我的路由器网关地址接收到数据时,它将映射到我的主机 192.168.1.101:1000,如下所示:

我还定义了以下客户端,在局域网的另一台机器(192.168.1.108)上运行:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;

namespace UDPClient
{
    class Program
    {
        static void Main(string[] args)
        {
            string ipOfServer = "205.172.111.250";
            int portServerIsListeningOn = 11000;

        // send data to server
        Socket sending_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        IPAddress send_to_address = IPAddress.Parse(ipOfServer);
        IPEndPoint sending_end_point = new IPEndPoint(send_to_address, portServerIsListeningOn);
        sending_socket.SendTo(Encoding.ASCII.GetBytes("Test"), sending_end_point);

        // get info
        var port = sending_socket.LocalEndPoint.ToString().Split(':')[1];

        // now wait for server to send data back
        IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, int.Parse(port));
        byte[] buffer = new byte[1024];
        sending_socket.Receive(buffer); // <----- we can receive data now!!!!!
    }
}

}

请注意ipOfServer。这是我的外部网关(不是真的,因为我混淆了它,但它不是 192.168.1.101 - 我的 UDP 服务器的内部 IP)。

当我指示客户端发送到192.168.1.101:11000的内部局域网IP时,UDP服务器连接。

但是,当我使用网关的IP地址和端口时,UDP服务器无法连接。由于我在 NAT 中将端口定向到 192.168.1.101:1000,我不确定是什么原因。

我知道 NAT 设置很好,因为我还有用于 HTTP 的端口 80 和用于 net.tcp 的端口 808 所有这些都可以在任何地方工作,甚至在我的网络之外。

请告诉我我做错了什么。

亲切的问候

如果不访问您的实际网络设置,就很难确切知道问题出在哪里。然而,创建一个套接字只是为了接收一些被丢弃的数据,然后才创建一个新的套接字,然后 "connect" 给客户端的方案似乎是错误的。您可能首先不应该将 Connect() 与 UDP 套接字一起使用,如果您觉得必须这样做,则应该在收到一些数据后连接原始套接字。

无论如何,您真正需要担心的是客户端方面的问题。您已经将路由器设置为转发服务器的入站数据报,因此服务器应该始终能够在该端口上接收数据。有问题的是到客户端的 return 流量;事实上,并非所有路由器都支持这种情况,并且始终需要为 UDP 流量进行端口转发(TCP 流量更容易,因为路由器可以与客户端保持持续连接)。

我建议您使服务器更简单——只需创建一个用于接收数据报的套接字(当然不要用 using 处理它)。我还建议不要使用 Connect(),因为这样做会不必要地限制服务器。 IE。它将阻止服务器的套接字能够处理多个客户端。如果你真的想做一些每个客户端的过滤,更好的机制是让服务器总是接收所有数据报,然后检查接收地址本身来决定如何处理数据报。