If you do not implement custom time, the default timeout for using system.net.sockets.socket are:
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.
The following is how 'ConnServer2SubProc1' will look like.
The following is how 'StartTimeoutTimer2' will look like.
The following is how 'TimeoutTimerTask2' will look like.
The usage of system.threading.readerwriterlock is important to prevent the race-condition between two processes which are dependent on the same variable '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.
- 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'..
- 'ConnServer2SubProc1' - Race to set 'undoConnTimeout' to True if the socket has been connected.
- '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