C#获取UDP服务器套接字从其接收数据的客户端的IP地址

标签 c# network-programming udp

我有一个很奇怪的问题。我无法找到我的服务器从中接收数据的客户端的 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 后面,公共(public) IP 为 214.214.214.214。

客户端是另一台机器,在另一台 NAT 后面,公共(public) IP 为 910.910.910.910。

客户端向服务器发送消息,服务器接收并读取内容。当服务器获取客户端的IPEndPoint时,显示的IP为214.214.214.214(服务器的IP,不是客户端)

编辑 也许我应该说,在我从我的 ISP 订购“动态 IP”之前,我无法从外部网络上的客户端接收消息。还是获取不到源的公网IP。

编辑 当使用 Wireshark 并嗅探从外部客户端发送到我的服务器的数据包时,我可以看到它也是错误的 src IP。下图中的 src IP 是我的服务器 IP,而不是发送数据的客户端 IP。

enter image description here

最佳答案

在阅读了几天我可能在路由器、网络上阅读的所有内容并编写了Receive、ReceiveFrom、ReceiveMessageFrom、BeginReceive、BeginReceiveFrom、BeginReceiveMessageFromReceiveAsync 的不同示例之后 -我已经解决了我的问题。

我更换了我的路由器。我现在可以使用非常旧的路由器获取外部客户端的源 IP。我之前使用的路由器是新的 Docsis 3.1。

为什么它与旧路由器一起工作,我不知道,但出于某种原因,Docsis 3.1 在让 UDP 消息到达我的机器之前将源 IP 更改为它自己的 IP。

关于C#获取UDP服务器套接字从其接收数据的客户端的IP地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52164557/

相关文章:

java - 我选择 UDP 作为我的 peer 2 peer 服务,我如何证明它在我的情况下是可靠的

c++ - 如何找到通过 UDP 发送数据所花费的时间

c# - 循环获取每一项的索引

c# - Firebase 远程配置 : Version condition is disabled for Unity projects

c# - 将数组转换为 IEnumerable<T>

java - 从 Android 应用程序自动在本地网络上查找服务器

web-services - Delphi 中的 Web 服务超时错误

network-programming - 专用网络(如 IPv4)问题

c - UDP 套接字无法接收 ECONNREFUSED

c# - WhenActivated 在 ViewModelViewHost 控件中托管的 Views 和 ViewModel 中使用时被调用两次