2012-03-16 69 views
1

我正在製作一個小型userControl庫,用於在特定端口[LAN]上搜索活動服務器。
我使用[.NET 4.0] TCP套接字(IPV4)
所以首先讓我的電腦IPAddresses來源:如何檢查數組<T>是否有重複值?

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

然後我把第一個3個部分的ip地址的,所以如果輸入ip地址=「192.168.1.X」它返回「192.168.1」。 使用:

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

然後我從搜索: -

我需要的是檢查是否 SCANIP是(前192.168.1 到192.168.1 。)因爲數組IpA可能會返回許多IP地址(無線網絡,有線網絡,藍牙網絡等) 例如:我的無線IP是:192.168.1.25 和我的ethern等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(); 
     } 
    } 
+0

因此,清楚地說,您希望構建一個獨特的scanIPs清單,它是IP的前三部分? – 2012-03-16 14:07:41

+0

@JamesMichaelHare是的。 – 2012-03-16 14:32:23

+0

不管別人打敗我:-) +1 HashSet! – 2012-03-16 14:35:03

回答

2

你可以使用HashSet的保持已經使用的地址。

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

if (!usedIp.Contains(scanIP)) 
{ 
    usedIP.Add(scanIP); 
    Parallel.For(1, 255, (i, loopState) => 
       { 
        Scan(scanIP + i); 
       }); 
} 
3

更換SomeCondition最簡單的方法是使用LINQ Distinct()擴展方法:

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); 
       }); 
     } 
    } 
+0

IpA.Distinct()沒有Length屬性 – 2012-03-16 14:15:37

+0

您是否確切地指IpA.Distinct()。Count()? – 2012-03-16 14:18:01

+0

這是我的錯。我糾正了答案。 – 2012-03-16 14:23:59

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); 
+1

自我自我詞典?這就是HashSet的用途:-) – 2012-03-16 14:16:07

+0

啊,是的。客戶端配置文件中沒有提供Hashset ,因此總是最終不得不解決字典問題。 – 2012-03-16 14:27:32

+0

夠公平:-) – 2012-03-16 14:27:53