如何在运行我的程序的本地网络上获取主机的IP地址

时间:2015-08-19 19:12:50

标签: c# sockets tcp port p2p

我已经构建了一个对等的C#视频会议应用程序,它使用特定的TCP端口(17500)进行音频通信。目前,在我的应用程序界面上,我输入了另一个打开程序以进行通信的IP地址。我想要做的是自动找到IP地址。

因此,我认为实现此目的的最佳方法是获取使用相同TCP端口号17500的本地IP地址。我该怎么做?或者是否有其他方法使用相同的应用程序获取IP地址?

3 个答案:

答案 0 :(得分:6)

如评论中所述,您需要某种对等发现协议。

由于许多多媒体设备,路由器等使用基于多播的发现协议,如SSDP,我创建了类似的发现服务样本。

用法很简单。只需使用

Discoverer.PeerJoined = ip => Console.WriteLine("JOINED:" + ip);
Discoverer.PeerLeft= ip => Console.WriteLine("LEFT:" + ip);

Discoverer.Start();

您的所有客户都将使用相同的代码。

using System;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Caching; // add this library from the reference tab
using System.Text;
using System.Threading.Tasks;

namespace SO
{
    public class Discoverer
    {
        static string MULTICAST_IP = "238.212.223.50"; //Random between 224.X.X.X - 239.X.X.X
        static int MULTICAST_PORT = 2015;    //Random

        static UdpClient _UdpClient;
        static MemoryCache _Peers = new MemoryCache("_PEERS_");

        public static Action<string> PeerJoined = null;
        public static Action<string> PeerLeft = null;

        public static void Start()
        {
            _UdpClient = new UdpClient();
            _UdpClient.Client.Bind(new IPEndPoint(IPAddress.Any, MULTICAST_PORT));
            _UdpClient.JoinMulticastGroup(IPAddress.Parse(MULTICAST_IP));


            Task.Run(() => Receiver());
            Task.Run(() => Sender());
        }

        static void Sender()
        {
            var IamHere = Encoding.UTF8.GetBytes("I AM ALIVE");
            IPEndPoint mcastEndPoint = new IPEndPoint(IPAddress.Parse(MULTICAST_IP), MULTICAST_PORT);

            while (true)
            {
                _UdpClient.Send(IamHere, IamHere.Length, mcastEndPoint);
                Task.Delay(1000).Wait();
            }
        }

        static void Receiver()
        {
            var from = new IPEndPoint(0, 0);
            while (true)
            {
                _UdpClient.Receive(ref from);
                if (_Peers.Add(new CacheItem(from.Address.ToString(), from),
                               new CacheItemPolicy() { 
                                    SlidingExpiration = TimeSpan.FromSeconds(20),
                                    RemovedCallback = (x) => { if (PeerLeft != null) PeerLeft(x.CacheItem.Key); }
                               }
                             )
                )
                {
                    if (PeerJoined != null) PeerJoined(from.Address.ToString());
                }

                Console.WriteLine(from.Address.ToString());
            }
        }
    }
}

现在关于算法的一点点:

  • 每个客户端每秒都会多播一个数据包。

  • 如果接收方(每个客户端都有)从一个不在其缓存中的IP获取数据包,它将触发 PeerJoined 方法。

  • 缓存将在20秒后过期。如果客户端没有从缓存中的另一个客户端收到该持续时间内的数据包,则会触发 PeerLeft 方法。

答案 1 :(得分:2)

我相信如果您使用点对点应用程序来交换数据包,当您需要知道某人是否“在线并准备连接”时,您需要发送广播。我们可以使用UDP连接轻松完成。

我将发布一个示例,其中您使用两种方法:一种是在广播消息中向整个网络询问现成的客户端,另一种是启动侦听器以回复广播询问消息,或者如果响应则启动连接“我在这里”的类型来了。

希望它有所帮助!

public sealed class UdpUtility
{
    // Our UDP Port
    private const int broadcastPort = 11000;

    // Our message to ask if anyone is ready for connection
    private const string askMessage = "ARE ANYONE OUT THERE?";

    // Our answer message
    private const string responseMessage = "I AM HERE!";

    // We use this method to look for a client to connect with us.
    // It will send a broadcast to the network, asking if any client is ready for connection.
    public void SendBroadcastMessage()
    {
        var udp = new UdpClient(broadcastPort);
        var endpoint = new IPEndPoint(IPAddress.Broadcast, broadcastPort);

        try
        {
            var bytes = Encoding.ASCII.GetBytes(askMessage);
            udp.Send(bytes, bytes.Length, endpoint);
        }
        catch (Exception ex)
        {
            // Treat your connection exceptions here!
        }
    }

    // This method will start a listener on the port.
    // The client will listen for the ask message and the ready message.
    // It can then, answer back with a ready response, or start the TCP connection.
    public void ListenBroadcastMessage()
    {
        var udp = new UdpClient(broadcastPort);
        var endpoint = new IPEndPoint(IPAddress.Broadcast, broadcastPort);

        bool received = false;

        try
        {
            while (!received)
            {
                // We start listening broadcast messages on the broadcast IP Address interface.
                // When a message comes, the endpoing IP Address will be updated with the sender IP Address.
                // Then we can answer back the response telling that we are here, ready for connection.
                var bytes = udp.Receive(ref endpoint);
                var message = Encoding.ASCII.GetString(bytes);

                if (message == askMessage)
                {
                    // Our client received the ask message. We must answer back!
                    // When the client receives our response, his endpoint will be updated with our IP Address.
                    // The other client can, then, start the TCP connection and do the desired stuff.
                    var responseBytes = Encoding.ASCII.GetBytes(responseMessage);
                    udp.Send(responseBytes, responseBytes.Length, endpoint);
                }
                else if (message == responseMessage)
                {
                    // We received a connection ready message! We can stop listening.
                    received = true;

                    // We received a response message! 
                    // We can start our TCP connection here and do the desired stuff.
                    // Remember: The other client IP Address (the thing you want) will be on the
                    // endpoint object at this point. Just use it and start your TCP connection!
                }
            }
        }
        catch (Exception ex)
        {
            // Treat your connection exceptions here!
        }
    }
}

答案 2 :(得分:-4)

调用命令提示符执行“netstat -n”并解压缩输出。

这是从我编写的程序中获取的一段代码,以满足您的要求。您仍需要进一步处理数据以获取IP地址

        Process netP = new Process();
        ProcessStartInfo netPI = new ProcessStartInfo();
        netPI.FileName = "cmd";
        netPI.UseShellExecute = false;
        netPI.RedirectStandardOutput = true;
        netPI.RedirectStandardInput = true;
        netPI.RedirectStandardError = true;
        netPI.CreateNoWindow = true;
        netP.StartInfo = NetPI;
        netP.Start();
        while (!netP.Start())
            Thread.Sleep(100);
        StreamWriter sW = netP.StandardInput;
        StreamReader sR = netP.StandardOutput;
        sW.WriteLine("netstat -n")
        sW.Close();
        string data = sR.ReadToEnd();
        sR.Close();
        //Do some further processing to filter out the addresses and extract