bck
Alejandro Acuña
2024-11-11 f1cb4443aede6d4657bdc3396c8914d3a9f4fa93
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
'***************************************************************************
'* 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