VB.NET Socket Custom Timeout

If you do not implement custom time, the default timeout for using system.net.sockets.socket are:
  • 2 seconds for IPs which are online. (when you are trying to connect to a port which no server is listening to)
  • 20 seconds for IPs which are offline.

This means that it will take at least 20 seconds for you to discover IPs which are offline. And if you want it faster, you got to implement custom timeout methods.

Here is one way!

Check out the sample codes (VB.NET Visual Studio 2008 SP1) and description.

To explain briefly.

The following codes (truncated) is responsible to invoke 'BeginConnect' and to start a thread which will perform the timeout process.

serverIP = "127.0.0.1"
localIP = System.Net.IPAddress.Parse(localIPStr)
localIPEndP = New System.Net.IPEndPoint(localIP, CInt(txtPortNum.Value))

tcpSocket = Nothing
tcpSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)

'====(Deprecated) Start a thread process to process timeout procedure
undoConnTimeout = False
connTimeoutCount = tempConnTimeout
Call StartTimeoutTimer2()
'======================================================================

tempACallback = New AsyncCallback(AddressOf ConnServer2SubProc1)
Call tcpSocket.BeginConnect(localIPEndP, tempACallback, Nothing)

The following is how 'ConnServer2SubProc1' will look like.

Private Sub ConnServer2SubProc1(ByVal ar As IAsyncResult)

        Try

            If Not tcpSocket Is Nothing Then
                If tcpSocket.Connected Then

                    '=== Retrieve writerlock here =============

                    If Not undoConnTOLock Is Nothing Then

                        undoConnTOLock.AcquireWriterLock(100) '10 ms
                        'undoConnTOLock.AcquireWriterLock(Timeout.Infinite)

                        If undoConnTOLock.IsWriterLockHeld Then

                            '=== (Deprecated) Undo Conn Time out =======
                            undoConnTimeout = True
                            '=====================================================================
                        Else
                            MsgBox("Fail to acquire lock@ConnServer2SubProc1", MsgBoxStyle.Critical)

                        End If 'If undoConnTOLock.IsWriterLockHeld Then

                    End If ' If Not undoConnTOLock Is Nothing Then
                    '=========================================

                    '=== start receiving data ================
                    If IsStartPolling Then
                        '=== Begin accepting data ============
                        Call ContinueNextPollThreadPool()

                    End If

                    Call UpdateLblDataSocketThreadSafe("Text socket connected!")
                Else
                    Call UpdateLblStatusThreadSafe("Connection timeout ..")
                    Call UpdateLblDataSocketThreadSafe("Text socket NOT connected!")
                End If
            Else
                MsgBox("Nothing")
            End If '  If Not tempSocket Is Nothing Then

        Catch ex1 As System.ApplicationException

            MsgBox("Fail to acquire lock@ConnServer2SubProc1", MsgBoxStyle.Critical)


        Catch ex As Exception

            MsgBox(ex.ToString & vbCrLf & ex.Message & vbCrLf & ex.StackTrace)

        End Try

    End Sub

The following is how 'StartTimeoutTimer2' will look like.

Private Sub StartTimeoutTimer2()

        Dim tempThread As System.Threading.Thread

        Dim tempThreadStart As System.Threading.ParameterizedThreadStart

        tempThreadStart = New System.Threading.ParameterizedThreadStart(AddressOf TimeoutTimerTask2)
        tempThread = New System.Threading.Thread(tempThreadStart)

        tempThread.IsBackground = True

        tempThread.Name = "TimeoutTimerTask2"

        '=== Start immediately ===============
        Call tempThread.Start()

    End Sub

The following is how 'TimeoutTimerTask2' will look like.

Private Sub TimeoutTimerTask2()

        Dim tempCount As Integer

        Try

            Do Until tempCount = connTimeoutCount
                '=== sleep for 1 second =============
                System.Threading.Thread.Sleep(1000)

                '=== increment the count ============
                tempCount += 1
            Loop

            '=== Retrieve writerlock here =============

            If Not undoConnTOLock Is Nothing Then

                undoConnTOLock.AcquireWriterLock(100) '10 ms
                'undoConnTOLock.AcquireWriterLock(Timeout.Infinite)

                If undoConnTOLock.IsWriterLockHeld Then

                    If Not undoConnTimeout Then

                        If Not tcpSocket Is Nothing Then

                            tcpSocket.Close()

                        End If 'If Not tcpSocket Is Nothing Then

                    End If 'If Not undoConnTimeout Then
                Else
                    'MsgBox("Fail to acquire lock @ TimeoutTimerTask2")
                    Call UpdateLblStatusThreadSafe("Fail to acquire lock @ TimeoutTimerTask2")
                End If 'If undoConnTOLock.IsWriterLockHeld Then

            End If 'If Not undoConnTOLock Is Nothing Then

        Catch ex1 As System.ApplicationException

            'MsgBox("Fail to acquire lock @ TimeoutTimerTask2", MsgBoxStyle.Critical)
            Call UpdateLblStatusThreadSafe("Fail to acquire lock @ TimeoutTimerTask2")

        Catch ex As Exception
            MsgBox(ex.ToString & vbCrLf & ex.Message & vbCrLf & ex.StackTrace)
        End Try

    End Sub

The usage of system.threading.readerwriterlock is important to prevent the race-condition between two processes which are dependent on the same variable 'undoConnTimeout'..
  1. 'ConnServer2SubProc1' - Race to set 'undoConnTimeout' to True if the socket has been connected.
  2. 'TimeoutTimerTask2' - Race to invoke 'close' on the socket by evaluating the value (boolean) of 'undoConnTimeout'


The implementation of the system.threading.readerwriterlock is crucial because both processes 'Callback Process' and 'Timeout Process' may occur simultaneously. This is the big deal.

Comments