locked
TcpClient connection timeout

    Question

  • How do I implement a timeout for the connect method of a TcpClient?  For example, what if the host is offline?  Right now when I try to execute this sub and the host is not available the code times out after 25 seconds or so.  Since the connection is never made, the SendTimeout and ReceiveTimeout never come in to play.  My code is as follows:

    Private Sub SendFile(ByVal file() As Byte, ByVal address As String, ByVal port As Integer)

    Dim clientSocket As System.Net.Sockets.TcpClient

    Dim networkStream As System.Net.Sockets.NetworkStream

    Try

    clientSocket = New System.Net.Sockets.TcpClient

    clientSocket.SendTimeout = 1000

    clientSocket.ReceiveTimeout = 1000

    clientSocket.Connect(address, port)

    networkStream = clientSocket.GetStream()

    networkStream.WriteTimeout = 1000

    networkStream.Write(file, 0, file.Length)

    networkStream.Close()

    clientSocket.Close()

    Catch ex As Exception

    MessageBox.Show(ex.Message)

    End Try

    End Sub

    Wednesday, January 10, 2007 6:04 PM

Answers

  • Socket.ReadTimeout and Socket.WriteTimeout has nothing to do with Conneciton Time out, there is no such thing in Managed Sockets (Dont know about Native Ones)....

    So what you can do is that you create a timer and put its interval to be 5000 for 5 Seconds, Now call Begin Connection, when the Tick event of timer is fired check to see if Socket was connected in that duration or not, If done then good otherwise call EndConnect explicily to cancel the Connection Request....

    Note: Make sure to set a flag when connected in Connect Callback event.

    I hope this will help.

    Best Regards,

    Rizwan aka RizwanSharp

    Thursday, January 11, 2007 3:59 PM
  • The timeout value is going to be user-configurable meaning that it may decrease or it may increase.  What I think I'll have to do is implement something like your suggestion, but in a loop.

    Thanks for the info and suggestion.

    Thursday, January 11, 2007 4:09 PM

All replies

  • AFAIK, there is no such direct method or property available in Socket and related classes that you can use for Connect timeout.

    But if you want to solve a problem that
    If host is not available then Connect method takes long time to come back and your code execution getting blocked till that.

    If you want to overcome this issue then you can use asynch method available for connect.. I mean BeginConnect so it will not block the main execution flow...

    HTH,

    Thursday, January 11, 2007 2:59 PM
  • Socket.ReadTimeout and Socket.WriteTimeout has nothing to do with Conneciton Time out, there is no such thing in Managed Sockets (Dont know about Native Ones)....

    So what you can do is that you create a timer and put its interval to be 5000 for 5 Seconds, Now call Begin Connection, when the Tick event of timer is fired check to see if Socket was connected in that duration or not, If done then good otherwise call EndConnect explicily to cancel the Connection Request....

    Note: Make sure to set a flag when connected in Connect Callback event.

    I hope this will help.

    Best Regards,

    Rizwan aka RizwanSharp

    Thursday, January 11, 2007 3:59 PM
  • The timeout value is going to be user-configurable meaning that it may decrease or it may increase.  What I think I'll have to do is implement something like your suggestion, but in a loop.

    Thanks for the info and suggestion.

    Thursday, January 11, 2007 4:09 PM
  • For posterity, here's the solution I ended up with.  There might be a few bugs in there, but this seems to be working so far.

    Public Class Form1

    Private clntSockParams As clientSocketParameters

    Private UserTimeoutTime As New Timers.Timer

    Private clientSocket As System.Net.Sockets.TcpClient

    Private Structure clientSocketParameters

    Public addrs As String

    Public prt As Integer

    End Structure

    Private Sub UserTimeoutTime_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)

    If UserTimeoutTime.Enabled Then

    Try

    'This is actually DISPOSING of clientSocket It'll need to be recreated if it's going to be called again.

    clientSocket.Close()

    Catch ex As Exception

    'Nothing to really do here, just fail silently

    End Try

    'Set it to nothing so that we can test if it has been .Close()'d

    clientSocket = Nothing

    UserTimeoutTime.Stop()

    End If

    'The asynchronous connect will return after being .Close()'d so the ConnectionReturned sub will fire next

    End Sub

    Private Sub ConnectionReturned(ByVal ar As System.IAsyncResult)

    If UserTimeoutTime.Enabled Then 'Make sure the timer is still running

    'Check to make sure the clientsocket wasn't Close()'d

    If clientSocket Is Nothing Then

    clientSocket = New System.Net.Sockets.TcpClient

    End If

    'Check if the connection succeeded before the UserTimeoutTime has elapsed

    If clientSocket.Connected Then

    UserTimeoutTime.Stop()

    Else

    'If the UserTimeoutTime hasn't elapsed yet, try again.

    Dim actualparameters As clientSocketParameters = DirectCast(ar.AsyncState, clientSocketParameters)

    clientSocket.BeginConnect(actualparameters.addrs, actualparameters.prt, New AsyncCallback(AddressOf ConnectionReturned), clntSockParams)

    End If

    End If

    End Sub

    Private Sub SendFile(ByVal file() As Byte, ByVal address As String, ByVal port As Integer)

    Dim networkStream As System.Net.Sockets.NetworkStream

    AddHandler UserTimeoutTime.Elapsed, AddressOf UserTimeoutTime_Elapsed

    UserTimeoutTime.Interval = Me.txtTimeout.Text * 1000

    UserTimeoutTime.Start()

    clntSockParams.addrs = address

    clntSockParams.prt = port

    Try

    clientSocket = New System.Net.Sockets.TcpClient

    clientSocket.SendTimeout = Me.txtTimeout.Text * 1000

    clientSocket.ReceiveTimeout = Me.txtTimeout.Text * 1000

    clientSocket.BeginConnect(address, port, New AsyncCallback(AddressOf ConnectionReturned), clntSockParams)

    'Wait for the connection to succeed - this mimics synchronous behavior

    Do While UserTimeoutTime.Enabled

    System.Threading.Thread.Sleep(500)

    Loop

    If clientSocket Is Nothing Then

    Throw New Exception("Connection timed out.")

    Else

    networkStream = clientSocket.GetStream()

    networkStream.WriteTimeout = Me.txtTimeout.Text * 1000

    networkStream.Write(file, 0, file.Length)

    networkStream.Close()

    clientSocket.Close()

    End If

    Catch ex As Exception

    MessageBox.Show(ex.Message)

    End Try

    End Sub

    End Class

    Sunday, January 14, 2007 2:32 AM