2012-03-16 336 views
3

我一直在閱讀關於如何檢查局域網上特定端口上的所有監聽服務器,最後我寫了一些代碼,它可以工作,因爲我想要的。
我使用System.Threading.Tasks.Parallel儘可能快地連接到所有254個IP地址
ex: 192.168.1。 - 192.168.1。如何設置Socket.ConnectAsync的超時時間?

我需要做的是爲這些連接嘗試超時,因爲它需要約15-20秒打印:「連接失敗」,當它失敗..所以我該怎麼辦呢?

這裏的客戶端代碼:

static void Main(string[] args) 
    { 
     Console.WriteLine("Connecting to IP addresses has started. \n"); 

     Parallel.For(1, 255, i => 
     { 
      Connect("192.168.1." + i); 
     }); 
     Console.ReadLine(); 
    } 

    private static void Connect(string ipAdd) 
    { 
     Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
     SocketAsyncEventArgs e = new SocketAsyncEventArgs(); 
     IPEndPoint ipEnd = new IPEndPoint(IPAddress.Parse(ipAdd), 9990); 
     e.RemoteEndPoint = ipEnd; 
     e.UserToken = s; 
     e.Completed += new EventHandler<SocketAsyncEventArgs>(e_Completed); 
     Console.WriteLine("Trying to connect to : " + ipEnd); 
     s.ConnectAsync(e); 
    } 
    private static void e_Completed(object sender, SocketAsyncEventArgs e) 
    { 
     if (e.ConnectSocket != null) 
     { 
      StreamReader sr = new StreamReader(new NetworkStream(e.ConnectSocket)); 
      Console.WriteLine("Connection Established : " + e.RemoteEndPoint + " PC NAME : " + sr.ReadLine()); 
     } 
     else 
     { 
      Console.WriteLine("Connection Failed : " + e.RemoteEndPoint); 
     } 
    } 

服務器代碼:

static void Main(string[] args) 
    { 
     Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
     IPEndPoint ep = new IPEndPoint(IPAddress.Any,9990); 
     server.Bind(ep); 
     server.Listen(100); 
     Socket client = server.Accept(); 
     NetworkStream stream = new NetworkStream(client); 
     StreamWriter sw = new StreamWriter(stream) 
     sw.WriteLine(System.Environment.MachineName); 
     sw.Flush(); 
     sw.Dispose(); 
     stream.Dispose(); 
     client.Dispose(); 
     server.Dispose(); 
    } 

如果有使得它更告訴我任何提示或通知。我正在使用[.Net 4.0]套接字TCP
對不起,我的英語不好,在此先感謝..

+1

15-20秒似乎是合理的一個連接嘗試和254次的嘗試非常好。如果服務器關閉,我的瀏覽器花費的時間比「旋轉箭頭」模式中的時間要長。 – 2012-03-16 08:24:01

+0

實際上,如果鏈路有撥號調制解調器,則20秒太短。幸運的是,這樣的恐怖事件幾乎全部消失了。 – 2012-03-16 08:27:00

+1

@MartinJames這是一個局域網,正如我所提到的..大多數顯示主機可用的遊戲和應用程序..在不到10秒內給出結果。像[pc任何地方,netsupport,半衰期..等等]我知道他們使用更好的算法和方法來得到那個..但我需要它在很短的時間 – 2012-03-16 08:32:14

回答

3

我已經想出了一個解決方案。
首先創建的套接字添加類型的列表的SocketAsyncEventArgs插座
的類型 然後使用System.Timers.Timer以關閉所有掛起連接,並且當計時器滴答後的連接的一個,其是在5秒後。 (timer.Interval = 5000)。

客戶端代碼:

//I've changed my console application to Winform 
    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) 
    { 
     timer.Start(); 
     Parallel.For(1, 255, (i, loopState) => 
     { 
      ConnectTo("192.168.1." + i); 
     }); 
    } 

    private void ConnectTo(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);  // Add to a list so we dispose all the sockets when the timer ticks. 
     s.ConnectAsync(e); 
    } 

    private void e_Completed(object sender, SocketAsyncEventArgs e) 
    { 
     if (e.ConnectSocket != null)  //if there's a connection Add its info to a listview 
     { 
      StreamReader sr = new StreamReader(new NetworkStream(e.ConnectSocket)); 
      ListViewItem item = new ListViewItem(); 
      item.Text = sr.ReadLine(); 
      item.SubItems.Add(((IPEndPoint)e.RemoteEndPoint).Address.ToString()); 
      item.SubItems.Add("Online"); 
      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();  //disposing all sockets that's pending or connected. 
     } 
    } 

enter image description here

1

我找不到任何內置的超時機制。您應該設置一個計時器並在觸發時中止連接。類似的東西:How to configure socket connect timeout

+1

我不確定..創建一個外部計時器喜歡創建一個新的線程..它似乎不好創建254個計時器 – 2012-03-16 06:33:38

+1

也許我會爲所有他們設置一個計時器..但我仍然更喜歡一個更好的主意 – 2012-03-16 06:35:36

+2

您只需要一個計時器,因爲它對所有連接都是相同的超時時間。 – zmbq 2012-03-16 07:47:39