当前位置: 首页 > 知识库问答 >
问题:

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

虞祯
2023-03-14

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

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

编辑以澄清问题:

服务器托管在我的机器上,位于公共 IP 为 214.214.214.214 的 NAT 后面。

客户端是另一台计算机,位于另一台具有公共 IP 910.910.910.910 的 NAT 后面。

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

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

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

共有2个答案

百里意智
2023-03-14

使用Udp客户端类,您实际上可以在接收消息时检索远程endpoint。

我使用了如下所示的解决方案来解决此任务:

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}");
}
万俟鸿波
2023-03-14

几天来,我尽可能地阅读了路由器、网络上的所有内容,并编写了不同的Receive、ReceiveFrom、ReceiveMessageFrom、BeginReceiveFrom、BeginReceiveMessageFrom和ReceiveAsync示例,现在我已经解决了这个问题。

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

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

 类似资料:
  • 我是 python 和套接字的新手,正在尝试编写一个回显客户端/服务器套接字。我已经编写了服务器,以便丢失 30% 的数据包。我将客户端编程为在一秒后超时,因为数据包可能会丢失。但是,每当我运行客户端套接字时,我的输出都是 100% 请求超时。我假设我得到这个输出,因为我的服务器从未收到过消息。我已经多次查看了我的代码,但无法弄清楚为什么我不断获得此输出。下面是我的服务器和客户端套接字的代码。任何

  • 我正在尝试使用UDP在服务器(在公共IP上)和客户端(通过NAT)之间进行双向通信。我的逻辑是,如果服务器向IP和它接收数据包的端口发送一些数据,客户端仍然应该得到它,因为NAT最终会有将数据包发送到客户端的映射。 客户端有 2 个进程,一个用于发送数据包,另一个进程用于接收数据。服务器继续等待数据,如果它获得数据,它会将数据发送回从接收数据的端口和 IP。 客户代码如下: client_recv

  • 我想做的是: 为了学习游戏编程,我使用专用服务器和UDP创建了一个回声设置。专用服务器在不同的城市(也就是不在我的本地网络中)。 在我的本地计算机上,我有一个udp客户端和服务器(两个不同的程序)。当我第一次启动python服务器时,windows防火墙立即询问我是否要添加异常。在允许我的python服务器联网之后,我仍然没有收到任何消息。(客户- 我的问题是: 游戏如何解决这个问题?我没有为我想

  • 我已经在Minikube上部署了一个UDP套接字服务器。套接字服务绑定到端口2152。下面是description pod命令中的IP片段。 我的客户机与minikube运行在同一个VM上,无法与服务器通信。我在客户端使用服务器地址IP 172.17.0.3,端口为2152。我还尝试使用minikube IP 192.168.49.2将UDP数据从客户端发送到服务器。 请帮忙,这里有什么问题。

  • 真的需要你帮忙。 我的项目是通过电缆连接两台PC机,并使用tcp套接字将客户端文本框形式的字符串发送到服务器。问题是ATI只能发送一个字符串,然后连接就会关闭。 注意:某个端口上的连接将在表单加载中建立并成功。

  • Java: 在C#中-它停止在“receiver=listener.accept();”在java(android)中-它停止于“sender_socket=new Socket(serverAddr,SERVERPORT);”这应该是java套接字函数的问题--需要另一个函数连接到C#-server。