【发布时间】:2018-09-04 10:49:23
【问题描述】:
我有一个很奇怪的问题。我无法找到我的服务器从中接收数据的客户端的 IP 地址。下面是我的 UDP Listener 类。
IPPacketInformation 不包含 IP。我在 EndReceiveMessageFrom 中引用的 clientEndPoint 两者都没有。
当我
Console.Writeline(((IPEndPoint)clientEndPoint).Address);
我得到了服务器的 IP 地址。我将服务器托管在我自己的机器上,所以我有自己的 IP 地址。当我尝试访问 clientEndPoint.remoteEndPoint 时,它会抛出一个错误,因为套接字未连接(由于是 UDP)。
所以基本上,来自外部 IP 的客户端能够发送数据,但我无法回答客户端,因为我无法检索它的 IP。任何帮助表示赞赏!
public class UdpListener
{
private Socket s;
public byte[] ReceiveBuffer = new byte[2048];
public UdpListener()
{
s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.PacketInformation, true);
s.Bind(new IPEndPoint(IPAddress.Any, 36200));
}
public void Listen()
{
try
{
EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
s.BeginReceiveMessageFrom(ReceiveBuffer, 0, ReceiveBuffer.Length, SocketFlags.None, ref remoteEndPoint, Recv, s);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
throw;
}
}
private void Recv(IAsyncResult res)
{
try
{
Socket receiveSocket = (Socket)res.AsyncState;
EndPoint clientEndPoint = new IPEndPoint(IPAddress.Any, 0);
IPPacketInformation packetInfo;
SocketFlags flags = SocketFlags.None;
int udpMessageLength = receiveSocket.EndReceiveMessageFrom(res, ref flags, ref clientEndPoint, out packetInfo);
byte[] udpMessage = new byte[udpMessageLength];
Array.Copy(ReceiveBuffer, udpMessage, udpMessageLength);
Console.WriteLine(
"{0} bytes received from {1} to {2}",
ReceiveBuffer,
clientEndPoint,
packetInfo.Address
);
EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, ((IPEndPoint)receiveSocket.LocalEndPoint).Port);
s.BeginReceiveMessageFrom(ReceiveBuffer, 0, ReceiveBuffer.Length, SocketFlags.None, ref remoteEndPoint, Recv, s);
//Process data
RaiseDataReceived(new ReceivedDataArgs(packetInfo.Address, ((IPEndPoint)clientEndPoint).Port, udpMessage));
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
throw;
}
}
public delegate void DataReceived(ReceivedDataArgs args);
public event DataReceived DataReceivedEvent;
private void RaiseDataReceived(ReceivedDataArgs args)
{
DataReceivedEvent?.Invoke(args);
}
}
我尝试禁用我的防火墙,但没有帮助。我还在路由器上完成了端口转发,因此我可以从外部客户端接收数据。
编辑以澄清问题:
服务器托管在我的机器上,位于公共 IP 214.214.214.214 的 NAT 后面。
客户端是另一台机器,位于另一个具有公共 IP 910.910.910.910 的 NAT 后面。
客户端向服务器发送消息,服务器接收并能够读取内容。服务器获取到客户端的IPEndPoint后,显示的IP为214.214.214.214(服务器的IP,不是客户端)
编辑 也许我应该说,在我从 ISP 订购“动态 IP”之前,我无法接收来自外部网络客户端的消息。还是拿不到源的公网IP。
编辑 当使用 Wireshark 并嗅探从外部客户端发送到我的服务器的数据包时,我可以看到它也是错误的 src IP。在下图中,src IP 是我的服务器 IP,而不是发送数据的客户端的 IP。
【问题讨论】:
-
为什么要收听端口零? IPEndPoint(IPAddress.Any, 0);
-
我正在侦听端口 36200。如果您的意思是 remoteEndPoint 或 clientEndPoint 端口 0,那么只要收到消息,endPoint 就会被覆盖
-
你考虑过使用UdpClient吗?
-
我试过了。结果相同。我也尝试过 Receive、ReceiveFrom、ReceiveAsync。
-
您确定端口号的overderriding 工作正常吗?我从来没有听说过监听器启动后端口号会发生变化。
标签: c# network-programming udp