我有一个将数据(服务器)发送到 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 连接到远程主机?谢谢
总结/详细说明一下评论:
由于不知道大家对网络了解多少: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,源 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 '相互交谈'。正因为如此,它才知道如何处理来自您的服务器的数据包!
现在让我们尝试相反的方式。有两种可能的情况:
服务器知道您客户端的 IP (192.168.0.100)。回想一下,互联网上的任何设备都不知道这个 IP,因此如果它发出一个 IP 数据包(dest 192.168.0.100,源 81.82.83.84),它将不会到达网关,因为到达网关的唯一数据包是那些具有目标 IP 为 47.46.43.42 。这个选项永远不会起作用。
服务器知道网关的 IP 并发出一个 IP 数据包(目的地 47.46.43.42,源 81.82.83.84)。该数据包将到达网关。但是网关应该怎么做呢?它从不记得来自 IP 81.82.83.84 的数据包应该转发到您的客户端。网关学习的唯一方法是客户端首先向您的服务器发送数据包。此选项也不起作用。
因此,它并没有足够*服务器知道客户端的IP,但网关需要了解你的服务器和客户端之间的“对话”。和你的网关的工作方式要求客户端发送出一个包第一,使用精确的端口发送要进一步使用。如果您的服务器应该向您的客户端 UDP 端口 2 发送数据,则客户端必须首先从 UDP 端口 2 向服务器发送数据包。
您的网关所做的是NATTING,您最好阅读一下它。
但是,我假设您的网络有一些标准设置。这很可能,但从技术上讲,它可能完全不同,也许您的网关充当防火墙,也部分阻止传出流量,也许您的服务器配置为也将您的网关用作网关(很奇怪,但技术上可行)。
因此,离线故障排除很困难,如果我不能在这里为您提供具体问题的解决方案 (TM) ,我很抱歉。
PS:您可能想知道为什么您的客户端可以使用错误的目标 IP 向网关发送数据包,而您的服务器却不能。这与以下事实有关,即在以太网层,您的 LAN 是单个网络,而 Internet 不是...
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句