'*************************************************************************** '* ClassTCPClient * '* * '* This class manages the TCP connection with an E301 module. * '* It tries to keep the connection alive checking continously it by * '* sending pings. If the connection is lost it tries to connect again. * '* Once connected, this class provides a function to send data to the * '* E301 and an event to trap the data received. * '* * '* EQUITEL C.V. February 2007 ALMDI* '*************************************************************************** Imports System Imports System.Net Imports System.Net.Sockets Imports System.Threading Imports System.Text Imports System.IO Imports System.Net.NetworkInformation Imports System.Globalization Imports System.Timers Public Class ClassTCPClient #Region "Definitions" 'Time between pings to the destination IP in miliseconds Private Const CheckingTime As Integer = 3000 #End Region #Region "Fields" Private mStream As Stream Private mHostIP As String Private mHostPort As String Private mReceivingThread As Thread Private mTcpClient As TcpClient Private WithEvents mPingClient As New Ping() Private WithEvents mTimerPing As New System.Timers.Timer #End Region #Region "Events" Public Event ConnectionTerminated As EventHandler Public Event DataReceived As TCPDataReceivedEventHandler Public Event ConnectionSuccesful As EventHandler Public Event ConnectionFailed As EventHandler Public Event ConnectionLost As EventHandler Protected Overridable Sub OnConnectionTerminated() RaiseEvent ConnectionTerminated(Me, New EventArgs) End Sub Protected Overridable Sub OnConnectionSuccessful() RaiseEvent ConnectionSuccesful(Me, New EventArgs) End Sub Protected Overridable Sub OnConnectionFailed() RaiseEvent ConnectionFailed(Me, New EventArgs) End Sub Protected Overridable Sub OnConnectionLost() RaiseEvent ConnectionLost(Me, New EventArgs) End Sub Protected Overridable Sub OnDataReceived(ByVal Data() As Byte, ByVal Size As Integer) Dim e As New TCPDataReceivedEventArgs e.Data = Data e.Lenght = Size RaiseEvent DataReceived(Me, e) End Sub #End Region #Region "Properties" Public Property HostIP() As String Get HostIP = mHostIP End Get Set(ByVal Value As String) mHostIP = Value End Set End Property Public Property HostPort() As String Get HostPort = mHostPort End Get Set(ByVal Value As String) mHostPort = Value End Set End Property Public ReadOnly Property Connected() As Boolean Get Connected = mTcpClient.Connected End Get End Property #End Region #Region "Methods" 'Constructor Public Sub New(ByVal Ip As String, ByVal ControlPort As Integer) mHostIP = Ip mHostPort = ControlPort.ToString TryInitConnection() End Sub Private Sub OnEndTryingConnection(ByVal Ar As IAsyncResult) If Ar.IsCompleted Then If mTcpClient.Connected Then 'The connection has been possible 'Stream to send packets mStream = mTcpClient.GetStream() 'Thread to read incoming packets mReceivingThread = New Thread(AddressOf ReadData) mReceivingThread.Start() 'Start the connection status checking mTimerPing.Start() OnConnectionSuccessful() Else 'The connection is not possible mTimerPing.Stop() OnConnectionFailed() 'Let's try again TryInitConnection() End If End If End Sub Public Sub TryInitConnection() 'Tries to establish a TCP connection with the E301 module Dim RequestCallback As AsyncCallback Dim State As Object Dim ReturnValue As IAsyncResult mTcpClient = New TcpClient() mTcpClient.ReceiveTimeout = 0 'Waits forever for incoming packets mTimerPing.Interval = CheckingTime RequestCallback = New AsyncCallback(AddressOf OnEndTryingConnection) State = New Object ReturnValue = mTcpClient.BeginConnect(HostIP, CInt(HostPort), RequestCallback, State) End Sub Public Sub Disconnect() mReceivingThread.Abort() mTimerPing.Stop() mStream.Close() mTcpClient.Close() End Sub Public Sub SendData(ByVal Data() As Byte) If Not (mStream Is Nothing) Then mStream.Write(Data, 0, Data.Length) End If End Sub Private Sub ReadData() Dim ReadBuffer() As Byte Dim BytesLeidos As Integer Dim Ex As System.Net.Sockets.SocketException While True Try ReadBuffer = New Byte(100) {} 'Wait until data arrives BytesLeidos = mStream.Read(ReadBuffer, 0, ReadBuffer.Length) 'Data has arrived... OnDataReceived(ReadBuffer, BytesLeidos) Application.DoEvents() Catch e As IOException 'Some error... the conection is lost Ex = e.InnerException Console.WriteLine("ErrorCode: " & Ex.ErrorCode.ToString) Console.WriteLine("ERROR: " & Ex.ToString) OnConnectionTerminated() Exit While End Try End While End Sub Private Sub OnTimerPingFired(ByVal Sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles mTimerPing.Elapsed 'Send a ping and wait for a response at the most for the time between 'checkings minus one second (and no more than 10 seconds). 'This is done in order to not overlap the 'processes when the connection is lost. If there is no connection, the waiting 'process of one ping mus be terminated before sending a new one. Dim WaitingTime As Integer WaitingTime = CheckingTime - 1000 If WaitingTime > 10000 Then WaitingTime = 10000 Try mPingClient.SendAsync(mHostIP, WaitingTime, Nothing) Catch End Try End Sub Private Sub OnPingClientResponse(ByVal Sender As Object, ByVal e As System.Net.NetworkInformation.PingCompletedEventArgs) Handles mPingClient.PingCompleted 'Treats the response of the ping agent Dim NoPingResponse As Boolean = False If e.Error Is Nothing Then If e.Reply.Status = IPStatus.TimedOut Then NoPingResponse = True End If Else NoPingResponse = True End If If NoPingResponse Then OnConnectionFailed() Disconnect() TryInitConnection() End If End Sub #End Region End Class