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



我有一个向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方法中发送到远程端点。我尝试过许多不同的异步服务器示例,它们都会导致各种错误。有没有什么简单的方法可以更改此代码,使其能够通过互联网连接到远程主机?感谢

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

  • 您有一个具有公共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向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.43:1)。注意,服务器只"看到"网关,而不是它后面的客户端!网关接收到该数据包,回忆起它刚刚发送了一个IP数据包(dest 47.46.43.42:1,源192.168.0.100:2),假设该IP数据包是某种答案,并向您的客户端发送一个包含从服务器接收到的内容的新IP数据包。

特别注意,这只适用于,因为网关收到了来自客户端的数据包,并从中了解到192.168.0.100和81.82.83.84"相互通信"。正因为如此,它才知道如何处理来自服务器的数据包!

现在让我们换一种方式试试。有两种可能的情况:

  1. 服务器知道您的客户端的IP(192.168.0.100)。回想一下,互联网上的任何设备都不知道这个IP,因此,如果它发送一个IP数据包(dest 192.168.0.100,source 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向服务器发送数据包。

你的网关所做的是NATING,你最好读一读。

然而,我认为,你的网络有一些标准设置。这是可能的,但从技术上讲,这可能完全不同,也许你的网关充当防火墙,也部分阻断了传出流量,或者你的服务器也被配置为将你的网关用作网关(奇怪,但技术上可能)。

因此,离线故障排除很困难,如果我不能在这里为您的具体问题提供解决方案(TM),我很抱歉。

PS:你可能想知道为什么你的客户端可以向目标IP错误的网关发送数据包,而你的服务器却不能。这与以下事实有关,即在以太网层上,您的局域网是一个单一的网络,而互联网不是。。。

最新更新