简体   繁体   English

如何获取正在侦听特定端口LAN的所有服务器的IP?

[英]How do I get all servers' IP which are listening on specific port LAN?

How do I get all servers IP which are listening on specific port (Ex:9090) in LAN I have already read some basics information about multicast, anycast , unicast and broadcast and it seems like broadcast is the one meant for my application. 如何获取在LAN中侦听特定端口(例如:9090)的所有服务器IP我已经阅读了有关多播, anycastunicastbroadcast一些基本信息,看起来broadcast是我的应用程序的一个。 I am thinking of two ideas .. 我在考虑两个想法..

  • Use TCP protocol to Connect to all IP Addresses (192.168.1. 1-254 ) in parallel on port 9090 and set a little time period to the connection timeout. 使用TCP协议来并行连接到所有IP地址(192.168.1。1-254)在端口9090,并设置一个小的时间段到连接超时。 just to check if there's any responce. 只是为了检查是否有任何反应。 (but it doesn't seem like a good idea) (但这似乎不是一个好主意)
  • Use UDP protocol and broadcast a message like "hello" and check for response then get all IP Addresses which respond. 使用UDP协议并广播“hello”之类的消息并检查响应然后获取响应的所有IP地址。

    So which idea should I pick, are there better ideas to do it? 那么我应该选择哪种想法,是否有更好的想法呢? I would also like to know if my broadcast-ed message is received to the server and how to get the IP address of it. 我还想知道我的广播信息是否收到服务器,以及如何获取它的IP地址。

  • I've done it with TCP to search all server that is listening on a specific port. 我已经用TCP来完成搜索正在侦听特定端口的所有服务器。 Its not an idle solution, but it worked for me. 它不是一个闲置的解决方案,但它对我有用。

    I've created a userControl with a public function Initialize to pass the port that i want to scan for servers. 我创建了一个带有公共函数Initialize的userControl,以传递我想要扫描服务器的端口。

    在此输入图像描述

    public ServerDiscovery()
        {
            InitializeComponent();
        //    statusLabel.Image = imageState.Images[2];
            timer.Elapsed += timer_tick;
        }
        int port = 0;
        bool busy = false;  // to tell that the function is busy with scanning.
        public void Initialize(int port)
        {
            this.port = port;
        }
    
        System.Timers.Timer timer = new System.Timers.Timer(5000);
        List<SocketAsyncEventArgs> list = new List<SocketAsyncEventArgs>();
        // this list to hold all sockets that created to connect to IP .. to DISPOSE it later
        HashSet<string> usedIP = new HashSet<string>();
        //usedIP will be explained later. 
    
        public IPEndPoint getAddress()
        {   //this function to get the IPEndPoint of the selected server from listview.
            if (listServer.SelectedItems.Count > 0)
            {
                if (listServer.SelectedItems[0].ImageIndex == 0)
                {
                    ListViewItem item = listServer.SelectedItems[0];
                    IPEndPoint ep = new IPEndPoint(IPAddress.Parse(item.SubItems[1].Text), port);
                    return ep;
                }
            }
            return null;
        }
    
        public void Refresh()   //to scan for servers
        {
            if (!busy)
            {
                usedIP.Clear();
                listServer.Items.Clear();
        //       statusLabel.Text = "Scanning for servers.";
        //        statusLabel.Image = Image.FromFile("loading.gif");
        //        btnRefresh.Enabled = false;
                busy = true;
                timer.Start();
                IPAddress[] IpA = Dns.GetHostByName(Dns.GetHostName()).AddressList;
                for (int j = 0; j < IpA.Length ; j++)
                {
                    if (IpA[j].AddressFamily == AddressFamily.InterNetwork)  // to make sure it's an IPV4
                    {
                        string scanIP = IpA[j].ToString().Substring(0, IpA[j].ToString().LastIndexOf(".")) + ".";
                        if (!usedIP.Contains(scanIP))
                 //usedIP is a hashset that holds the first 3 parts on an ip (ex:"192.168.1." from "192.168.1.30") i used this to avoid scanning the same ip addresses more than once .. like if i had a wireless network ip ("192.168.1.5") and an Ethernet Network ip ("192.168.1.5"). so with that hashset it will scan once.
                        {
                            usedIP.Add(scanIP);
                            Parallel.For(1, 255, i =>
                            {
                                Scan(scanIP + i);
                            });
                        }
                    }
                }
            }
        }
    
        private void Scan(string ipAdd)
        {
            Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            SocketAsyncEventArgs e = new SocketAsyncEventArgs();
            e.RemoteEndPoint = new IPEndPoint(IPAddress.Parse(ipAdd), port);
            e.UserToken = s;
            e.Completed += new EventHandler<SocketAsyncEventArgs>(e_Completed);
            list.Add(e);   // add the created socket to a list to dispose when time is up.
            s.ConnectAsync(e);
        }
    
        private void e_Completed(object sender, SocketAsyncEventArgs e)
        {
            if (e.ConnectSocket != null) //if there's a responce from the server [e.ConnectSocket] will not be equal null.
            {
                StreamReader sr = new StreamReader(new NetworkStream(e.ConnectSocket));
                ListViewItem item = new ListViewItem();
                string[] cmd = sr.ReadLine().Split('<');  in my server constructor this line will receive a string like "PC_NAME<Available"  ..
                item.Text = cmd[0];
                item.SubItems.Add(((IPEndPoint)e.RemoteEndPoint).Address.ToString());
                item.SubItems.Add(cmd[1]);
                if (cmd[1] == "Busy")
                    item.ImageIndex = 1;
                else
                    item.ImageIndex = 0;
                AddServer(item);
                list.Remove(e);  //active server should be remove from the list that holds the sockets and disposed.. because there's no need to keep connection after showing that this server is active. 
                ((Socket)e.UserToken).Dispose();
            }
        }
    
        delegate void AddItem(ListViewItem item);
        private void AddServer(ListViewItem item)
        {
            if (InvokeRequired)
            {
                Invoke(new AddItem(AddServer), item);  //just to add an item from a background thread.
                return;
            }
            listServer.Items.Add(item);
        }
    
        private void timer_tick(object sender, EventArgs e)
        {
            busy = false;     //when time's up .. set busy to false so we can scan again
            timer.Stop();
            foreach (var s in list) //dispose all sockets that's trying to connect and waiting for a response
            {
                try
                {
                    ((Socket)s.UserToken).Dispose();
                }
                catch { }
            }
            //this.Invoke((MethodInvoker)delegate        // for design
           // {
           //     btnRefresh.Enabled = true;
           //     btnRefresh.BorderStyle = Border3DStyle.Raised;
           //     statusLabel.Text = "Ready.";
           //     statusLabel.Image = imageState.Images[2];
           // });
        }
    
        private void btnRefresh_Click(object sender, EventArgs e)
        {
           // btnRefresh.BorderStyle = Border3DStyle.Sunken;
            Refresh();
        }
    
       // private void listServer_KeyUp(object sender, KeyEventArgs e)
       // {
        //    if (e.KeyCode == Keys.F5)
        //    {
         //       btnRefresh_Click(sender, (EventArgs)e);
         //   }
      //  }
    
    
    }
    

    Again this's not an ideal solution that works on any case but it worked fine with me. 同样,这不是一个适用于任何情况的理想解决方案,但它适用于我。

    声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

     
    粤ICP备18138465号  © 2020-2024 STACKOOM.COM