Introduction
You will notice that neither of the two classes, System.Net.Sockets.TcpClient
nor System.Net.Sockets.Socket
has a timeout to connect a socket. I mean a timeout you can set. .NET Sockets do not provide a Connect Timeout when calling the Connect
/BeginConnect
method while establishing a Synchronous/Asynchronous socket connection. Instead, connect is forced to wait a very long time before an Exception is thrown if the server it tried to connect to is not listening or if there is any network error. The default timeout is 20 - 30 seconds. There is an option in socket library named SocketOptionName.SendTimeout
which is used for timeouts on Send data not initial connects.
Background
I have posted this code snippet on my blog to connect with destination machine with timeout using socket programming after solving the issue for one of my projects. Many people gave thanks for that. So I think that if I post it on The Code Project, many people can get it if they need it. For that reason, I am posting it here. I know it is a very simple task and should not be an article on The Code Project.
Using the Code
Here this functionality is implemented as a class. The class is as follows:
class TimeOutSocket
{
private static bool IsConnectionSuccessful = false;
private static Exception socketexception;
private static ManualResetEvent TimeoutObject = new ManualResetEvent(false);
public static TcpClient Connect(IPEndPoint remoteEndPoint, int timeoutMSec)
{
TimeoutObject.Reset();
socketexception = null;
string serverip = Convert.ToString(remoteEndPoint.Address);
int serverport = remoteEndPoint.Port;
TcpClient tcpclient = new TcpClient();
tcpclient.BeginConnect(serverip, serverport,
new AsyncCallback(CallBackMethod), tcpclient);
if (TimeoutObject.WaitOne(timeoutMSec, false))
{
if (IsConnectionSuccessful)
{
return tcpclient;
}
else
{
throw socketexception;
}
}
else
{
tcpclient.Close();
throw new TimeoutException("TimeOut Exception");
}
}
private static void CallBackMethod(IAsyncResult asyncresult)
{
try
{
IsConnectionSuccessful = false;
TcpClient tcpclient = asyncresult.AsyncState as TcpClient;
if (tcpclient.Client != null)
{
tcpclient.EndConnect(asyncresult);
IsConnectionSuccessful = true;
}
}
catch (Exception ex)
{
IsConnectionSuccessful = false;
socketexception = ex;
}
finally
{
TimeoutObject.Set();
}
}
}
Here ManualResetEvent
plays the main role to implement this. It has a method WaitOne
which has an overload WaitOne(TimeSpan, Boolean)
. According to MSDN, WaitOne(TimeSpan, Boolean)
blocks the current thread until the current instance receives a signal, using a TimeSpan
to measure the time interval and specifying whether to exit the synchronization domain before the wait.
So in the main thread, we call TimeoutObject.WaitOne(timeoutMSec, false)
to block the main thread until timeout or till the signal has been got using TimeoutObject.Set()
. When waitone
faces timeout, then it returns timeout exception. Otherwise socket is successfully connected or it faced any network error.
Here BeginConnect
of tcpclient
is used because this method does not block. After calling BeginConnect
, we wait using waitone
. If BeginConnect
does not complete operation within timeout, then waitone
will signal and TimeoutException
is returned. If BeginConnect
does complete operation within timeout, then it will signal ManualResetEvent
using TimeoutObject.Set()
from the CallBackMethod
which we passed as delegate in BeginInvoke
that references the CallBackMethod
to invoke when the operation is complete.
Sample Code
Here a project has been attached which shows the feature “Socket Timeout Connect”.
Conclusion
Though it is very simple work, I have posted this because I think many people like me need this feature of socket programming. If you guys have any questions, I would love to answer.
History
- Initial release – 05/12/08