Click here to Skip to main content
Click here to Skip to main content
Go to top

Implementation of Connecting a Socket with Timeout in C#

, 5 Dec 2008
Rate this:
Please Sign up or sign in to vote.
Connect with destination machine with timeout using socket programming

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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Razan Paul (Raju)
Software Developer (Senior) CP
Australia Australia
I am an Independent Contractor in Brisbane, Australia. For me, programming is a passion first, a hobby second, and a career third.
 
My Blog: http://weblogs.asp.net/razan/
 

 



Comments and Discussions

 
GeneralMy vote of 3 Pinmemberblackout_12-Nov-12 23:17 
BugThis is not thread safe! If you use it in a multi-threaded context, you will be very sorry. PinmemberDavid McKenzie21-Nov-11 3:12 
GeneralRe: This is not thread safe! If you use it in a multi-threaded context, you will be very sorry. PinmemberMember 259271824-Jan-12 5:54 
GeneralIncreasing connect timeout. PinmemberDUMITRU Guraliuc6-Mar-11 23:07 
GeneralInvalidOperationException when calling TCPClient.GetStream after AsyncConnection [modified] PinmemberYaroslav Trofimov26-Aug-09 21:43 
Generalconfiguration Pinmembermsvs200916-Aug-09 23:26 
GeneralRe: configuration PinmemberRazan Paul (Raju)17-Aug-09 3:28 
GeneralUse AsyncWaitHandle on the IAsycResult - much easier. Pinmemberowen3756-May-09 10:04 
GeneralHi RazanPaul, nice article... PinmemberJelle Hissink9-Dec-08 8:17 
Always nice to see some async processing...
 
You might not know it, but you can make your code even more simple and remove the callback and ManualResetEvent completely by gabbing the IASyncResult and using the WaitHandle it has to wait for the completion.
 
Further you convert the remoteEndPoint.Address to a string to later parse it back as an ip address, you can just pass it happily to BeginConnect it has an overload for IPAddress.
 
    class TimeOutSocket
    {
        public static TcpClient Connect(IPEndPoint remoteEndPoint, int timeoutMSec)
        {
            TcpClient tcpclient = new TcpClient();
 
            IAsyncResult asyncResult = tcpclient.BeginConnect(remoteEndPoint.Address, remoteEndPoint.Port, null, null);
 
            if (asyncResult.AsyncWaitHandle.WaitOne(timeoutMSec, false))
            {
                try
                {
                    tcpclient.EndConnect(asyncResult);
                    return tcpclient;
                }
                catch
                {
                    tcpclient.Close();
                    throw;
                }
            }
            else
            {
                tcpclient.Close();
                throw new TimeoutException("TimeOut Exception");
            }
        }
    }
 
Edit:
Also the static fields don't allow you to call your method concurrently, in the above change these fields are no longer needed so it is now possible to concurrently call the TimeOutSocket.Connect method.
 

GeneralRe: BeginConnect completion PinmemberIgin10-Dec-08 23:39 
GeneralRe: BeginConnect completion PinmemberJelle Hissink11-Dec-08 9:18 
GeneralRe: BeginConnect completion PinmemberIgin11-Dec-08 10:42 
GeneralVery nice! Pinmemberclark75-Dec-08 22:20 
GeneralRe: Very nice! PinmemberRazanPaul6-Dec-08 4:06 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140916.1 | Last Updated 5 Dec 2008
Article Copyright 2008 by Razan Paul (Raju)
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid