1

I am looking for a way of setting up a tcpclient connection Asynchronously with timeout, I tried to find out the answers at How to set the timeout for a TcpClient?, but it's not working for me, I put the setup code into a task to avoid of blocking the main thread, timeout is needed cause the setup process may take more than 1 minutes to fail. Please help me to make timeout work.

using System;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;

namespace test
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            Connect();

            int seconds = 0;
            while (true)
            {
                Console.WriteLine("time elapsed: " + seconds.ToString());
                Thread.Sleep(1000);
                seconds += 1;
            }
        }

        public static async void Connect()
        {
            Tcp tcp = new Tcp();

            await tcp.BeginConnect("apple.com", 3);

            Console.WriteLine("connect end.");
        }
    }

    class Tcp
    {
        public async Task BeginConnect(string ip, int port)
        {
            var client = new TcpClient();
            Console.WriteLine("start connecting.");
            try
            {
                var succeed = false;
                await Task.Run(() =>
                {
                    var result = client.BeginConnect(ip, port, null, null);
                    succeed = result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5)); // timeout doesn't work
                    client.EndConnect(result);
                });

                if (succeed && client.Connected)
                {
                    Console.WriteLine("connected to server.");
                }
                else
                {
                    Console.WriteLine("failed to connect to server.");
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("exception: " + e.ToString());
            }
        }
    }
}

the connect method doesn't end after 5 seconds as expected, as long as exception thrown, the code after client.BeginConnect(ip, port, null, null); will never get executed.

Alex Xu
  • 11
  • 2
  • 1
    it took 225 seconds to throw out an exception saying: exception: System.Net.Sockets.SocketException (0x80004005): Connection timed out – Alex Xu Mar 27 '20 at 15:03
  • 1
    Does this answer your question? [How to configure socket connect timeout](https://stackoverflow.com/questions/1062035/how-to-configure-socket-connect-timeout), [another one](https://stackoverflow.com/questions/28158892/tcpclient-beginconnect-timeout), [one more](https://stackoverflow.com/questions/4583873/how-to-set-test-tcp-connection-timeout) – oleksa Mar 27 '20 at 16:34
  • I've just tried `var succeed = tcp.BeginConnect(IPAddress.Parse("8.8.8.8"), 8080, null, null).AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5));` and it takes exactly 5 seconds to wait for connection. You have a lot of Tasks wrapped over the `BeginConnect`. Please try the simplest case first – oleksa Mar 27 '20 at 16:55
  • The `EndConnect()` method blocks until the operation has completed. So all your code does is wait five seconds, and then block for the actual connect operation to complete, which of course takes the normal connection time-out period. You need to close the socket if you want to interrupt the connection attempt prematurely. See marked duplicate. – Peter Duniho Mar 27 '20 at 17:19
  • @Peter Duniho thanks for your answer that point out it's the EndConnect which blocked the thread synchronously. now should I wait for EndConnect to complete after timeout or just do nothing and reconnect again? – Alex Xu Mar 28 '20 at 08:41
  • _"should I wait for EndConnect to complete after timeout"_ -- that depends on what your goal is. Per the marked duplicates, if you want to interrupt the connection attempt (i.e. impose your own, earlier, timeout), then you have to close the socket. Closing the socket will cause your callback to be called, which in turn will itself call `EndConnect()`, which in turn will throw an `ObjectDisposedException`. At that point, you can just start over, or do whatever you like. – Peter Duniho Mar 28 '20 at 15:50

0 Answers0