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

时间:2015-02-21 17:03:41

标签: c# .net udp server

我有以下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,如下所示:

NAT Virtual Server setting

我还定义了以下客户端,它在LAN上的另一台计算机(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)。

当我指示客户端发送到内部LAN IP为192.168.1.101:11000时,UDP服务器会连接。

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

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

请告诉我一些关于我做错的事情。

亲切的问候

1 个答案:

答案 0 :(得分:1)

如果没有访问您的实际网络设置,很难确切地知道错误。但是,创建套接字的方案只是为了接收一些被丢弃的数据,然后才创建一个新的套接字,然后你就可以连接&#34;对客户来说,似乎错了。你可能不应该首先使用带有UDP套接字的Connect(),如果你觉得必须,你应该在收到一些数据后连接原始套接字。

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

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