C # Получение IP-адреса клиента, с которого сокет UDP-сервера получил данные - PullRequest
0 голосов
/ 04 сентября 2018

У меня очень странная проблема. Я не могу найти IP-адрес клиента, с которого мой сервер получает данные. Ниже мой класс прослушивателя UDP.

IPPacketInformation не содержит IP. clientEndPoint , на который я ссылаюсь в моем EndReceiveMessageFrom , не делает ни того, ни другого.

Когда я

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.

Клиент - это другая машина, за другим NAT с общедоступным IP-адресом 910.910.910.910.

Клиент отправляет сообщение на сервер, сервер получает его и может прочитать содержимое. Когда сервер получает IPEndPoint клиента, отображается IP-адрес 214.214.214.214 (IP-адрес сервера , а не клиента )

РЕДАКТИРОВАТЬ Может быть, я должен сказать, что я не мог получать сообщения от клиентов во внешних сетях, пока я не заказал "Динамический IP" у моего провайдера. Все еще не могу получить публичный IP-адрес источника.

EDIT При использовании Wireshark и прослушивании пакета, отправленного с внешнего клиента на мой сервер, я вижу, что это также неправильный src IP. На рисунке ниже src IP - это IP-адрес моего сервера, а не IP-адрес клиента, отправившего данные.

enter image description here

Ответы [ 2 ]

0 голосов
/ 08 сентября 2018

После нескольких дней чтения всего, что я мог, на маршрутизаторах, в сети и написания различных примеров Receive, ReceiveFrom, ReceiveMessageFrom, BeginReceive, BeginReceiveFrom, BeginReceiveMessageFrom и ReceiveAsync - I ' мы решили мою проблему.

Я изменил свой маршрутизатор. Теперь я могу получить исходный IP-адрес внешнего клиента, используя очень старый маршрутизатор. Маршрутизатор, который я использовал раньше, был новым Docsis 3.1.

Почему он работает со старым маршрутизатором, я не знаю, но по какой-то причине Docsis 3.1 изменил исходный IP на свой собственный IP, прежде чем пропустить UDP-сообщение на мою машину.

0 голосов
/ 06 сентября 2018

Используя класс 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}");
}
...