【问题标题】:UDP Client server: Usage over a WANUDP 客户端服务器:通过 WAN 使用
【发布时间】:2019-01-28 02:14:05
【问题描述】:

我有一个向 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 连接到远程主机? 谢谢

【问题讨论】:

  • 对于 UDP,没有建立连接。就协议而言,没有 UDP 连接之类的东西。
  • 好的,如何找到远程地址?我知道它可以通过 UDPClient 完成,因为我有这样的应用程序在互联网上运行。这不能用套接字来完成吗?
  • 视情况而定。假设您知道典型 wan 上可能发生的事情(例如 NATing 等):
  • 和通过 Internet 一样。整个基础架构通常假定您的客户端发送初始数据包。对于 TCP,这是在连接建立期间隐式完成的。 UDP 没有这样做。客户端将第一个数据报发送到您的服务器 - 只需发送一个虚拟 dgram。 dgram 包含一个源套接字(IP 和端口),然后您可以使用它从您的服务器发回(源套接字可能不是您在客户端实际发送的套接字 - 这应该无关紧要)。
  • 如果您想了解其背景,请阅读有关 NAT (en.m.wikipedia.org/wiki/Network_address_translation) 的信息。

标签: asynchronous udp client-server wan


【解决方案1】:

总结/详细说明一下 cmets:

  • 您有一个具有公共 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 未知,他们将不会向任何人交付。

如果您的客户端尝试向您的服务器端口 1 发送 UDP 数据包,它将向网关发送一个包含目标 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 向 47.46.43.42 端口 1 发送了一个数据包,它自己的端口 15。每当一个 UDP 数据包到达在来自 47.46.43.42 的端口 15 上,它可以假设它是一些应该转发到 192.168.0.100 端口 2 的回复。

那么如果服务器收到数据包,它看到的只是(目标 IP 47.46.43.42:1,源 IP 81.82.83.84:83:15)。如果它想发回一个答案,它将发送一个带有(dest 81.82.83.84:15,source 47.46.43.42:1)的IP数据包。请注意,服务器仅“看到”网关,而不是您的客户端!网关接收到数据包,回忆起它刚刚发送了一个 IP 数据包(dest 47.46.43.42:1,source 192.168.0.100:2),假设 IP 数据包是某种应答,并发送一个新的 IP 数据包(dest 192.168 .0.100:2, source 47.46.43.42:1) 与从服务器接收到您的客户端的内容。

特别注意,这只能工作因为网关从客户端收到了一个数据包,并从中了解到 192.168.0.100 和 81.82.83.84 '相互交谈'。正因为如此,它才知道如何处理来自您服务器的数据包!

现在让我们反过来试试。有两种可能的情况:

  1. 服务器知道你的客户端的IP(192.168.0.100)。回想一下,互联网中的任何设备都不知道此 IP,因此如果它发送一个 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 是不够的,但网关需要了解您的服务器和服务器之间的“对话”客户。您的网关的工作方式要求客户端首先发送一个数据包,准确地使用您想要进一步使用的发送端口。如果您的服务器应该向您的客户端发送 UDP 端口 2,则客户端必须首先从 UDP 端口 2 向服务器发送数据包。

您的网关所做的是NATTING,您最好阅读一下它。

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

因此,离线故障排除很困难,如果我无法在此处为您的具体问题提供解决方案 (TM),我深表歉意。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-22
    • 2012-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    • 2022-08-18
    相关资源
    最近更新 更多