首页 文章

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

提问于
浏览
12

我有一个非常奇怪的问题 . 我无法找到我的服务器从中接收数据的客户端的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);
    }
}

我试图禁用我的防火墙,但这没有帮助 . 我还在路由器上完成了端口转发,因此我可以从外部客户端接收数据 .

EDIT 澄清问题:

服务器托管在我的机器后面的NAT公共IP 214.214.214.214 .

客户端是另一台机器,在公共IP 910.910.910.910的另一台NAT后面 .

客户端向服务器发送消息,服务器接收消息并能够读取内容 . 当服务器获取客户端的IPEndPoint时,显示的IP为214.214.214.214(服务器的IP, not the Client

EDIT 也许我应该说我没有得到源的公共IP .

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

enter image description here

2 回答

  • 6

    经过几天阅读我可能在路由器,网络和写入Receive,ReceiveFrom,ReceiveMessageFrom,BeginReceive,BeginReceiveFrom,BeginReceiveMessageFrom和ReceiveAsync的不同示例的所有内容 - 我已经解决了我的问题 .

    I changed my router. 我现在可以使用非常旧的路由器获取外部客户端的源IP . 我以前使用的路由器是一个新的Docsis 3.1 .

    为什么它适用于旧路由器,我不知道,但由于某种原因,Docsis 3.1在将UDP消息发送到我的机器之前将源IP更改为其自己的IP .

  • 1

    使用 UdpClient 类,您可以在接收消息时实际检索远程 endpoints .

    我使用了以下解决方案来解决此任务:

    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}");
    }
    

相关问题