David Dury
David Dury

Reputation: 5717

TcpClient ConnectAsync get status

Is there any way I can get the status of a TcpClient async connection? Using the following code, how can I get the status of the client using the Connected property? I try to establish a remote connection asynchronously but in the same time don't wait more then 5 seconds ...

TcpClient client = new TcpClient();

Task tsk = Task.Factory.StartNew(() =>
{
   client.ConnectAsync(host, port);

   // client.Connect   (this is always false)
});

tsk.Wait(5000);

// client.Connect   (or if I use it here, this is always false)

Upvotes: 3

Views: 15334

Answers (3)

Panagiotis Kanavos
Panagiotis Kanavos

Reputation: 131374

.Result and .Wait(...) are blocking, not asynchronous. The asynchronous way to connect with a timeout is to use a CancellationToken created by a CancellationTokenSource set to trigger after that timeout :

var cts=new CancellationTokenSource(TimeSpan.FromSeconds(5));
...
await client.ConnectAsync(host,port,cts.Token);

Upvotes: 2

Taai
Taai

Reputation: 2760

No, @Jon is wrong! The IsCompleted will just tell you if the task has been completed, it doesn't not indicate that the connection has been made. For example, if no server is open on the specific address/port, IsCompleted will return true anyway... You should check IsFaulted instead.

Here is code, that I have put together from pieces of the internet and I have actually tested:

string address = "127.0.0.1";
int port = 8888;
int connectTimeoutMilliseconds = 1000;

var tcpClient = new TcpClient();
var connectionTask = tcpClient
    .ConnectAsync(address, port).ContinueWith(task => {
        return task.IsFaulted ? null : tcpClient;
    }, TaskContinuationOptions.ExecuteSynchronously);
var timeoutTask = Task.Delay(connectTimeoutMilliseconds)
    .ContinueWith<TcpClient>(task => null, TaskContinuationOptions.ExecuteSynchronously);
var resultTask = Task.WhenAny(connectionTask, timeoutTask).Unwrap();

var resultTcpClient = resultTask.GetAwaiter().GetResult();
// Or by using `await`:
// var resultTcpClient = await resultTask.ConfigureAwait(false);

if (resultTcpClient != null)
{
    // Connected!
}
else
{
    // Not connected
}

Upvotes: 15

Jon
Jon

Reputation: 437376

First off, do not create a new Task of your own; this is a bug. ConnectAsync already returns a Task that represents the connection attempt:

var tsk = client.ConnectAsync(host, port);
tsk.Wait(5000);

After the wait returns, check the IsCompleted property of the task; it will be true if and only if the connection was established.

Upvotes: 10

Related Questions