c# - 使用 IPAddress.Any 获取客户端的 IP

标签 c# .net sockets networking udp

我目前正在一个简单的 udp 客户端/服务器系统上工作,我偶然发现了以下内容:当我尝试在一个使用 UdpClient 的程序中获取 IPEndPoint 的 IP(我使用 IPAdress.Any 获取)时,它起作用了,我得到以下结果(最上面的一个):

image

但是当我使用普通套接字而不是 UdpClient 时,它无法区分客户端/IP(底部)。下面列出了两者的代码。我想使用套接字的原因是因为使用相同的类来发送和接收(不是同一个实例)很方便并且使代码更容易理解。

首先

bool messageReceived = false;
bool done = false;
const int listenPort = 11000;
UdpClient listener = new UdpClient(listenPort);
IPEndPoint receiveEP = new IPEndPoint(IPAddress.Any, listenPort);
string[] adresses = new string[2];
public void ReceiveCallback(IAsyncResult ar)
{
    int id = 0;
    Byte[] receiveBytes = listener.EndReceive(ar, ref receiveEP);
    for (int i = 0; i < adresses.Length; i++)
    {
        if (adresses[i] == receiveEP.Address.ToString())
        {
            id = i;
            break;
        }
        else if (adresses[i] == null)
        {
            id = i;
            adresses[i] = receiveEP.Address.ToString();
            break;
        }
    }
    byte[] a= Encoding.ASCII.GetBytes("Is anybody there?");
    listener.Send(a, a.Length, receiveEP);
    Console.WriteLine("Received message from {0} (client {1}):",    adresses[id],id);
    string receiveString = Encoding.ASCII.GetString(receiveBytes);
    if (receiveString == "stop")
    {
        done = true;
    }
    Console.WriteLine("Received: {0}", receiveString);
    messageReceived = true;
}
public void ReceiveMessages()
{
    Console.WriteLine("listening for messages");
    while(!done){
        try
        {
            messageReceived = false;
            if (!messageReceived)
            {
                listener.BeginReceive(new AsyncCallback(ReceiveCallback),  null);
            }
            while (!messageReceived)
            {
            }

        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }
    Console.WriteLine("Done receiving messages...");
    for (int i = 0; i < adresses.Length; i++)
    {
        if (adresses[i] != null)
        {
            Console.WriteLine(adresses[i]);
        }
    }
    Console.ReadLine();
    listener.Close();
}'

第二

bool messageReceived = false;
bool done = false;
const int listenPort = 11000;
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,  ProtocolType.Udp);
IPEndPoint receiveEP = new IPEndPoint(IPAddress.Any, listenPort);
string[] adresses = new string[2];
byte[] buffer = new byte[1024];
public void ReceiveMessages()
{
    listener.Bind(receiveEP);
    Console.WriteLine("listening for messages");
    while (!done)
    {
        try
        {
            messageReceived = false;
            if (!messageReceived)
            {
                listener.BeginReceive(buffer, 0,1024,SocketFlags.None,new AsyncCallback(ReceiveCallback), null);
            }
            while (!messageReceived)
            {
            }

        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }
    Console.WriteLine("Done receiving messages...");
    for (int i = 0; i < adresses.Length; i++)
    {
        if (adresses[i] != null)
        {
            Console.WriteLine(adresses[i]);
        }
    }
    Console.ReadLine();
    listener.Close();
}
public void ReceiveCallback(IAsyncResult ar)
{
    int id = 0;
    int read = listener.EndReceive(ar);
    for (int i = 0; i < adresses.Length; i++)
    {
        if (adresses[i] == receiveEP.Address.ToString())
        {
            id = i;
            break;
        }
        else if (adresses[i] == null)
        {
            id = i;
            adresses[i] = receiveEP.Address.ToString();
            break;
        }
    }
    Console.WriteLine("Received message from {0} (client {1}):", adresses[id], id);
    string receiveString = Encoding.ASCII.GetString(buffer,0,read);
    if (receiveString == "stop")
    {
        done = true;
    }
    Console.WriteLine("Received: {0}", receiveString);
    messageReceived = true;
}'

我已经尝试过 Socket.ReceiveMessageFrom() 并使用它返回的 packetinfo,但即使我从另一台机器发送,我最终也得到了服务器的 ip4。有人可以帮帮我吗?

最佳答案

尽管这从来不应该是问答类型的问题,但我找到了一种让它工作的方法,这意味着 receive() 只需使用即可将 groupEP 更改为数据包发送方的 IP Socket 而不是 UdpClient(我模仿了 UdpClient 的工作方式)。目前,它仍然是同步的(listener.Receive() 是一个阻塞调用),但在不久的将来会改变:

    private const int listenPort = 11000;
    public static int Main()
    {
        bool done = false;
        Listener listener = new Listener(listenPort);
        IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, listenPort);
        byte[] buffer = new byte[2048];
        string received_data;
        try
        {
            while (!done)
            {
                Console.WriteLine("Waiting for broadcast");
                buffer=listener.Receive(ref groupEP);
                received_data = Encoding.ASCII.GetString(buffer);
                Console.WriteLine("Received a broadcast from {0}: {1}", groupEP.ToString(), received_data);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
        return 0;
    }
}
public class Listener
{
    public Socket client;
    public AddressFamily adressFamily;
    byte[] byte_buffer = new byte[2048];
    public int port;
    public Listener(int p) 
    {
        port=p;
        adressFamily = AddressFamily.InterNetwork;
        IPEndPoint localEP;
        localEP = new IPEndPoint(IPAddress.Any, port);
        client = new Socket(this.adressFamily, SocketType.Dgram, ProtocolType.Udp);
        client.Bind(localEP);
    }
    public byte[] Receive(ref IPEndPoint remoteEP)
    {
        IPEndPoint ipEndPoint=new IPEndPoint(IPAddress.Any,port);
        EndPoint endPoint = (EndPoint)ipEndPoint;

        int num = client.ReceiveFrom(byte_buffer, 2048, SocketFlags.None, ref endPoint);
        remoteEP = (IPEndPoint)endPoint;
        if (num < 2048)
        {
            byte[] array = new byte[num];
            Buffer.BlockCopy(byte_buffer, 0, array, 0, num);
            return array;
        }
        return byte_buffer;
    }

关于c# - 使用 IPAddress.Any 获取客户端的 IP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34457820/

相关文章:

c# - 使用 LightweightExcelReader 将 Excel 转换为 JSON

c# - 如何在 XML 反序列化期间将 XML 字符串保留为字符串字段

c# - 使用带有动态匿名对象的 NHibernate 在 GroupBy 查询中进行选择

java - java.net.Socket 是否检测客户端超时?

c# - 如何在单选按钮列表中的正确站点上设置文本

C# MVC - 在 LINQ 查询中使用 LIKE

.net - 是否可以使用 WCF 服务而不是 WCF 数据服务来实现服务器端分页

.net - F# 中泛型类型的运行时强制

c - 我的 UDP 客户端服务器出了什么问题?

android - 无法在 android socketio 客户端与 socketio 服务器之间建立连接