c# - 如何设置 Socket.ConnectAsync 超时?

标签 c# multithreading sockets parallel-processing connect

我一直在阅读有关如何检查 LAN 上特定端口上的所有监听服务器的信息,最后我编写了一些代码,它可以按我的需要工作。
我正在使用 System.Threading.Tasks.Parallel 尽可能快地连接到所有 254 个 IP 地址
例如:192.168.1.1 - 192.168.1.254

我需要为这些连接尝试设置一个超时时间,因为它需要大约 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
抱歉我的英语不好,在此先感谢..

最佳答案

我想出了一个解决办法。
首先将所有创建的套接字添加到 SocketAsyncEventArgs 类型或Socket
类型的列表中 然后使用 System.Timers.Timer 关闭所有挂起的连接,并在计时器计时 5 秒后关闭连接的连接。 (计时器。间隔 = 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

关于c# - 如何设置 Socket.ConnectAsync 超时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9732713/

相关文章:

c# - (附加行为的)依赖属性未被附加属性(另一个附加行为的)更新

c# - 防止 URL 参数绑定(bind)

c# - Xamarin 蓝牙扫描

c# - .net 中的线程

java - 如何处理java.lang.Exception : Socket bind failed: [730013] exception

c# - 如何使用 C# 更新列表中的条目

java - 如果上一个任务未完成,如何不启动 ScheduledExecutorService 任务

C# BackgroundWorker 和 Com 端口问题

javascript - 加载源为 : (socketio) 的 &lt;script&gt; 失败

angularjs - 为什么angular-socket-io用 'Error during WebSocket handshake: Unexpected response code: 400?'提示