代码之家  ›  专栏  ›  技术社区  ›  Tom

UDP客户端服务器:通过广域网使用

  •  0
  • Tom  · 技术社区  · 6 年前

    我有一个将数据(服务器)发送到UDP客户端的应用程序。它在同一台计算机上运行得很好,而且只要我知道客户端的目标地址,它就可以在局域网上运行。然而,当我在互联网上做这件事时,它就不再工作了,因为它没有目标计算机的地址。以下是服务器代码:

    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 回复  |  直到 6 年前
        1
  •  1
  •   Michael Beer    6 年前

    对评论进行一点总结/阐述:

    • 您的主机没有公共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发送了一个数据包到47.46.43.42端口1自己的端口15。当一个UDP包从47.46.43.42到达端口15时,它可以假设它是一些应该转发到192.168.0.100端口2的应答。

    然后,如果服务器接收到数据包,它所看到的就是(dest IP 47.46.43.42:1,source IP 81.82.83.84:83:15)。如果它想发回一个应答,它将发送一个IP包(dest 81.82.83.84:15,source 47.46.43.42:1)。请注意,服务器只“看到”网关,而不是背后的客户端!网关接收数据包,回顾它刚刚发送了一个IP数据包(dest 47.46.43.42:1,源192.168.0.100:2),假设IP数据包是某种应答,并将一个新的IP数据包(dest 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包(dest 192.168.0.100,source 81.82.83.84),它将 达不到

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

    因此,它确实 足够*让服务器知道 客户端IP 第一

    你的网关是 NATTING ,你最好读一点。

    不过,我想你的网络应该是标准的。这很可能,但从技术上讲,可能是完全不同的,也许你的网关充当了防火墙,也部分阻止了传出流量,也许你的服务器也被配置成使用你的网关作为网关(奇怪,但从技术上讲是可能的)。

    因此脱机故障排除很困难,如果我不能给你 你的具体问题的解决方案。

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