我有一个非常奇怪的问题。我找不到服务器从中接收数据的客户端的IP地址。下面是我的UDP侦听器类。
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);
}
}
我尝试禁用防火墙,但这无济于事。我还在路由器上完成了端口转发,因此可以从外部客户端接收数据。
编辑以澄清问题:
服务器托管在我的计算机上的NAT后面,并具有公共IP 214.214.214.214。
客户端是另一台计算机,位于具有公共IP 910.910.910.910的另一个NAT之后。
客户端将消息发送到服务器,服务器接收到该消息并能够读取内容。当服务器获取客户端的IPEndPoint时,显示的IP为214.214.214.214(服务器的IP,不是客户端)
编辑也许我应该说,直到我从ISP订购了“动态IP”,我才能从外部网络上的客户端接收消息。仍然无法获得来源的公共IP。
编辑,当使用Wireshark并嗅探从外部客户端发送到我的服务器的数据包时,我也看到它也是错误的src IP。在下面的图片中,src IP是我的服务器IP,而不是发送数据的客户端的IP。
答案 0 :(得分:6)
几天后,我在路由器,网络上阅读了所有可能的内容,并编写了 Receive,ReceiveFrom,ReceiveMessageFrom,BeginReceive,BeginReceiveFrom,BeginReceiveMessageFrom 和 ReceiveAsync 的不同示例-我已经解决了我的问题。
我更改了路由器。现在,我可以使用非常旧的路由器来获取外部客户端的源IP。我以前使用的路由器是新的Docsis 3.1。
我不知道为什么它可以与旧路由器一起使用,但是由于某些原因,在让UDP消息进入我的计算机之前,Docsis 3.1将源IP更改为自己的IP。
答案 1 :(得分:1)
使用UdpClient
类,您实际上可以在收到消息时检索远程端点。
我使用以下解决方案来解决此任务:
public void StartServer()
{
var udpServer = new UdpClient(new IPEndPoint(IPAddress.Any, ConnectionInformation.DETECTION_PORT));
udpServer.BeginReceive(new AsyncCallback(detectionCallback), udpServer);
}
private void detectionCallback(IAsyncResult ar)
{
var client = (ar.AsyncState as UdpClient);
if (client.Client == null) return;
var endPoint = new IPEndPoint(IPAddress.Any, ConnectionInformation.DETECTION_PORT);
var bytes = client.EndReceive(ar, ref endPoint);
Debug.WriteLine($"Detection request from: {endPoint}");
}