UDP客户端服务器:通过WAN使用

时间:2018-08-21 20:33:18

标签: asynchronous udp client-server wan

我有一个将数据(服务器)发送到UDP客户端的应用程序。只要我知道客户端的目标地址,它就可以完美地在同一台计算机上并通过LAN运行。但是,当我通过Internet执行此操作时,它不再起作用,因为它没有目标计算机的地址。这是服务器代码:

public ServerSender(String address, Int32 port, int TTL)
{
  m_Address = address;
  m_Port = port;
  m_TTL = TTL;

  Init();
}

private Socket m_Socket;
private IPEndPoint m_EndPoint;
private String m_Address;
private Int32 m_Port;
private Int32 m_TTL;


private void Init()
{
  IPAddress destAddr = IPAddress.Parse(m_Address);

  m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 

  m_EndPoint = new IPEndPoint(destAddr, m_Port);     
}

public void SendBytes(Byte[] bytes)
{
  m_Socket.SendTo(bytes, 0, bytes.Length, SocketFlags.None, m_EndPoint);
}

这里是客户:

    public void Connect(string strAddress, int port)
    {
        m_Address = IPAddress.Parse(strAddress);
        m_Port = port;

        m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); // Multicast Socket

        m_Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);

        m_EndPoint = new IPEndPoint(m_Address, m_Port);

        m_Socket.Bind(m_EndPoint);

        m_Socket.Connect(m_EndPoint);

        IsConnected = true;

        this.DoRead();
    }

    private void DoRead()
    {
        try
        {
            m_Socket.BeginReceive(bytes, 0, bytes.Length, SocketFlags.None, new AsyncCallback(OnDataReceived), m_Socket);
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }
    }

显然,服务器将需要侦听远程连接,而客户端将需要连接到服务器。我认为我可以获取远程地址,然后在SendBytes方法中将其发送到远程端点。我尝试了许多异步服务器的不同示例,它们都导致各种错误。有没有简单的方法可以更改此代码,以允许其通过Internet连接到远程主机? 谢谢

1 个答案:

答案 0 :(得分:1)

总结一下/详细说明一下:

  • 您有一个具有公共IP的主机,即直接连接到inet(您的“服务器”)
  • 您有一台没有公共IP的主机,即通过某个网关/防火墙连接到inet ...(您的“客户端”)

由于我不知道您对网络了解多少: TCP / UDP数据包包装在IP数据包中。 IP处理IP地址,TCP和UDP知道端口,但是:TCP端口1和UDP端口1是不同的东西!

您的网络设置可能类似于,其中包含一些示例IP:

|--------|  47.46.43.42              |---------|192.168.0.1       |--------|
| Server |======== The INET =========| Gateway |==================| Client |
|--------|               81.82.83.84 |---------|     192.168.0.100|--------|

这里的网关是您的“路由器”。

您的客户端将被配置为将不属于本地LAN的任何流量发送到网关(如果您能够从客户端浏览网站,则会以正确的方式进行配置)。

再次注意:如果目标IP属于“其”网络,则网络设备会将IP数据包传递给适当的收件人。如果目标IP未知,它们将不会传递给任何人。

如果客户端尝试将UDP数据包发送到服务器端口1,它将向目的地网关发送包含目标IP 47.46.43.42和源IP 192.168.0.100的IP数据包,以及目标端口1和用于发送数据包的端口(假设端口2)。网关接收数据包,查看目标IP,然后将IP数据包的内容作为新IP数据包发送(目的地47.46.43.42:1,源81.82.83.84)。它必须使用另一个UDP端口进行发送,比方说15。这里的关键是:它还记得它从192.168.0.100端口2向其自己的端口15的47.46.43.42端口1发送了一个数据包。在47.46.43.42的端口15上,可以假定应该将某些答复转发到192.168.0.100端口2。

然后,如果服务器接收到数据包,则它所看到的就是(目标IP 47.46.43.42:1,源IP 81.82.83.84:83:15)。如果要发送回一个答案,它将发送一个IP数据包,其地址为(目的地81.82.83.84:15,源47.46.43.42:1)。请注意,服务器仅“看到”网关,而不是您的客户端在后面!网关收到数据包,回想它刚发送了一个IP数据包(目的47.46.43.42:1,源192.168.0.100:2),假定该IP数据包是某种应答,然后发送了一个新的IP数据包(目的192.168)。 .0.100:2,来源47.46.43.42:1),以及从服务器接收到的内容到客户端。

请特别注意,这仅适用于,因为网关收到了来自客户端的数据包,并据此得知192.168.0.100和81.82.83.84“互相讲话”。仅因为如此,它才知道如何处理从您的服务器收到的数据包!

现在让我们尝试另一种方法。有两种可能的情况:

  1. 服务器知道您客户端的IP(192.168.0.100)。回想一下,该IP对Internet上的任何设备都是未知的,因此,如果它发送IP数据包(目的192.168.0.100,源81.82.83.84),它将无法到达网关,因为唯一到达网关的数据包是目标IP为47.46.43.42的数据包。此选项将永远无法使用。

  2. 服务器知道网关的IP并发送IP数据包(目标47.46.43.42,源81.82.83.84)。该数据包将到达网关。但是网关应该如何处理呢?它从不记住,来自IP 81.82.83.84的数据包可能应该转发给您的客户端。 网关学习的唯一方法是客户端是否首先向您的服务器发送了一个数据包。此选项也不起作用。

因此,服务器知道客户端的 IP 还不够*,但是网关需要了解服务器与服务器之间的“会话”。客户。网关的工作方式要求客户端首先使用您要进一步使用的发送端口发送包 first 。如果您的服务器应将UDP端口2发送到客户端,则客户端必须首先从UDP端口2向服务器发送数据包。

您的网关要做的是NATTING,您最好了解一下。

但是,我假设您的网络是某些标准设置。这是可能的,但从技术上讲,它可能完全不同,也许您的网关充当防火墙,也部分阻止了传出流量,也许您的服务器也配置为也使用网关作为网关(奇怪,但在技术上可行)。

因此很难进行脱机故障排除,如果无法在此处为您提供具体问题的解决方案(TM),我们感到抱歉。

PS:您可能想知道为什么客户端 可以使用错误的目标IP将数据包发送到网关,而服务器却不能。这与以下事实有关:在ethernet layer上,您的LAN是单个网络,而Internet不是...