How can I set Socket.ConnectAsync timeout?

I was reading about how to test all listening servers on a specific port on a local network and finally I wrote some code that works the way I want.
I am using System.Threading.Tasks.Parallel to connect to all 254 IPs as fast as possible
ex: 192.168.1. 1 - 192.168.1. 254

I need to set a timeout for these connection attempts because it takes about 15-20 seconds to print: "Connection error" on failure. So how do you do it?

Here's the client code:

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

      

Server code:

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();
    }

      

If there is any hint or notice which is better, please let me know. I am using [.Net 4.0] Sockets TCP
Sorry for my bad english and thanks in advance.

+3


source to share


2 answers


I figured out the solution.
first add all created sockets to the list of type SocketAsyncEventArgs or type Socket or
then use System.Timers.Timer to close all pending connection and connected after timer closes after 5 seconds. (timer .Interval = 5000).

Client code:



   //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 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 pending or connected.
        }
    }

      

enter image description here

+3


source


I couldn't find a built-in timeout mechanism. You must set a timer and abort connections when it starts. Something similar to this: How to configure the socket connection timeout



+1


source







All Articles