我有一个简单的C#UDP服务器,它在不同的线程上运行一个侦听器和一个发送器。侦听器在指定端口上绑定到当前计算机,并侦听任何传入的UDP数据包。编写器会将数据发送到给定的endpoint,这在某些情况下是可行的。
我现在遇到的问题是,当UDP数据包在侦听端口上发送到我的公共IP时,它们不会被接收,但是,如果我将公共IP更改为我的路由器IP(192.168.0.2),那么它就可以正常工作。这不是我要找的,因为托管服务器只能发送到客户端的公共IP。
流程
发送方(5.5.5.5″,1000)通过UDP将数据发送到给定endpoint(1.2.3.4″,1000)
服务器(1.2.3.4″,1000)接收数据
使用发件人的公共IP和侦听端口(5.5.5.5″,1000)将数据回传给发件人
为什么即使在给定端口上侦听,数据也没有被发送回公共ip?
当本地测试时,在同一台机器上运行服务器和客户端,当endpoint设置为我的公共IP和侦听端口时,本地根本无法接收数据。
Program()
{
ipep = new IPEndPoint(IPAddress.Any, 1000);
listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
listenSocket.Bind(ipep);//this should bind to port 1000
Thread listenThread = new Thread(listen);
Thread writeThread = new Thread(send);
listenThread.Start();
writeThread.Start();
listenThread.Join();
writeThread.Join();
}
void listen()
{
Console.WriteLine("Starting listener for echoback...");
while (true)
{
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
EndPoint epSender = (EndPoint)sender;
byte[] buffer = new byte[1024];
listenSocket.ReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref epSender);
string receivedString = Encoding.ASCII.GetString(buffer, 0, buffer.Length);
Console.WriteLine("Received via UDP: " + receivedString);
}
}
void send()
{
while (true)
{
byte[] msg = Encoding.ASCII.GetBytes("Test message".ToCharArray());
//when this is router IP 192.168.0.2, it works fine, but not for public ip
UdpClient client = new UdpClient("PUBLIC IP", 1000);
client.Send(msg, msg.Length);
Thread.Sleep(2000);
}
}
}
我注意到当UDP数据包被“服务器”接收时,发送端口总是不同的,我读到你需要在这个IP/端口上回复,但是客户端没有在接收端口上侦听,所以我用发送端的地址和它应该侦听的端口创建了一个新的endpoint。那么,在客户端-服务器通过UDP不断进行通信的情况下,游戏或其他应用程序如何管理这个问题。
欢迎来到NAT遍历的世界。其中IP地址被转换,端口号不能一致地映射。
你正在尝试的是被称为纳特发夹。NAT后面的客户端节点试图发送到自己的公共IP地址。不是所有的NAT都支持这个模式…这就是为什么发送到您的私有IP地址工作,但不是您的公共IP地址。当您的NAT接收到带有指定到其自己的公共IP的IP地址的数据报时,它不知道要将其发送回众多节点中的哪一个(您的pc,您的电话,您的游戏机等。。。)。所以它只是丢弃数据包。