1

我正在制作一个小型 userControl 库,用于在特定端口[LAN]上搜索活动服务器。
我正在使用 [.Net 4.0] TCP 套接字(IPV4)
,所以首先我从以下位置获取计算机的 IPAddresses:

string sHostName = Dns.GetHostName();
IPHostEntry ipE = Dns.GetHostByName(sHostName);
IPAddress[] IpA = ipE.AddressList;

然后我取 IPAddress 的前 3 部分,所以如果输入 IPAddress =“192.168.1.X”,它将返回“192.168.1”。使用 :

string scanIP = IpA[i].ToString().Substring(0, IpA[i].ToString().LastIndexOf(".")) + ".";

然后我从(例如: 192.168.1. 1 - 到 192.168.1. 254)搜索

我需要检查scanIP是否重复以避免多次扫描254个IP地址。因为数组IpA可能会返回许多IP地址(无线网络,有线网络,蓝牙网络..等),例如:我的无线IP是:192.168 .1.25,我的以太网 IP 是:192.168.1.5

这是我的代码:

  public ServerDiscovery()
    {
        InitializeComponent();
        timer.Elapsed += timer_tick;
    }

    System.Timers.Timer timer = new System.Timers.Timer(5000);
    List<SocketAsyncEventArgs> list = new List<SocketAsyncEventArgs>();

    private void btnRefresh_Click(object sender, EventArgs e)
    {
        listServer.Items.Clear();
        timer.Start();
        //getting array of IP Addresses.
        IPAddress[] IpA = Dns.GetHostByName(Dns.GetHostName()).AddressList;

        for(int j = 0; j < IpA.Length; j++)
        {
            if (IpA[j].AddressFamily == AddressFamily.InterNetwork)  //checking if IP is version 4
            {
                string scanIP = IpA[j].ToString().Substring(0, IpA[j].ToString().LastIndexOf(".")) + ".";
                if (some condition)// i need a condition to ensure that dublicated scanIP doesn't scan again
                {
                    Parallel.For(1, 255, (i, loopState) =>
                        {
                            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), 9990);
        e.UserToken = s;
        e.Completed += new EventHandler<SocketAsyncEventArgs>(e_Completed);
        list.Add(e);
        s.ConnectAsync(e);
    }

    private void e_Completed(object sender, SocketAsyncEventArgs e)
    {
        if (e.ConnectSocket != null)
        {
            StreamReader sr = new StreamReader(new NetworkStream(e.ConnectSocket));
            ListViewItem item = new ListViewItem();
            string[] cmd = sr.ReadLine().Split('<');
            item.Text = cmd[0];
            item.SubItems.Add(((IPEndPoint)e.RemoteEndPoint).Address.ToString());
            item.SubItems.Add(cmd[1]);
            AddServer(item);
        }
    }

    delegate void AddItem(ListViewItem item);
    private void AddServer(ListViewItem item)
    {
        if (InvokeRequired)
        {
            Invoke(new AddItem(AddServer), item);
            return;
        }
        listServer.Items.Add(item);
    }

    private void timer_tick(object sender, EventArgs e)
    {
        timer.Stop();
        foreach (var s in list)
        {
            ((Socket)s.UserToken).Dispose();
        }
    }
4

3 回答 3

3

最简单的方法是使用Distinct()LINQ 扩展方法:

    IpA = IpA.Distinct().ToArray();
    for(int j = 0; j < IpA.Length; j++)
    {
    ...

您还可以使用 HashSet 来检查重复项。我认为这是一个更快的解决方案:

    HashSet<IPAddress> set = new HashSet<IPAddress>(IpA);
    for(int j = 0; j < IpA.Length; j++)
    {
        if( set.Contains(IpA[j]) )
            continue;
        set.Add(IpA[j]);

        if (IpA[j].AddressFamily == AddressFamily.InterNetwork)  //checking if IP is version 4
        {
            string scanIP = IpA[j].ToString().Substring(0, IpA[j].ToString().LastIndexOf(".")) + ".";
            Parallel.For(1, 255, (i, loopState) =>
                {
                    Scan(scanIP + i);
                });
        }
    }
于 2012-03-16T14:10:06.837 回答
2

您可以使用 HashSet 来保留已使用的地址。

HashSet<string> usedIP = new HashSet<string>();

将 SomeCondition 替换为

if (!usedIp.Contains(scanIP))
{
   usedIP.Add(scanIP);
   Parallel.For(1, 255, (i, loopState) =>
                {
                     Scan(scanIP + i);
                });
}
于 2012-03-16T14:09:24.663 回答
0

将 scanIP 添加到字典中,并确保尚未添加它。

Dictionary<string, string> scannedIPs = new Dictionary<string, string>();

...

string scanIP = IpA[j].ToString().Substring(0, IpA[j].ToString().LastIndexOf(".")) + ".";
if (!scannedIPs.ContainsKey(scanIP))
{
   scannedIPs.Add(scanIP, scanIP);
于 2012-03-16T14:13:05.887 回答