Find all our projects in development below.
All source code is GNU General Public License (GPL)
Browsing clsTcpClient.vb (8.43 KB)
Option Explicit On
Imports System.Net
Imports System.Net.Sockets
Imports System.Text.Encoding
Imports System.Threading
Public Class clsTcpClient
Implements IDisposable
Private thisSock As Socket = Nothing
Private thisThread As Thread = Nothing
Private pollThread As Thread = Nothing
Private callbackDataRecvStringFunc As TcpClientDataRecvStringFunc = Nothing
Private callbackDataRecvByteFunc As TcpClientDataRecvByteFunc = Nothing
Private callbackDisconnectSub As TcpClientDisconnectSub = Nothing
Public ReadOnly TcpServer As clsTcpServer = Nothing
Public Delegate Function TcpClientDataRecvStringFunc(ByVal strData As String) As String
Public Delegate Function TcpClientDataRecvByteFunc(ByVal byteData() As Byte) As Byte()
Public Delegate Sub TcpClientDisconnectSub(ByVal thisClient As clsTcpClient)
Private Const SOCKET_RECV_TIMEOUT = 2000 ' 2 seconds
Private Const SOCKET_SEND_TIMEOUT = 2000 ' 2 seconds
Private Const LOOP_SLEEP_DELAY = 10 ' 1/100 second
Private Const POLL_SLEEP_DELAY = 100 ' 1/10 second
Public Sub New(ByVal ip As String, ByVal port As Integer, _
Optional ByVal clientDisconnectCallback As TcpClientDisconnectSub = Nothing)
' instantiate a new tcp socket
thisSock = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
' configure the socket
thisSock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, SOCKET_RECV_TIMEOUT)
thisSock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, SOCKET_SEND_TIMEOUT)
' connect to the remote host
thisSock.Connect(IPAddress.Parse(ip), port)
Me.callbackDisconnectSub = clientDisconnectCallback
' start polling for a disconnect
_startPoll()
End Sub
Public Sub New(ByVal server As clsTcpServer, ByVal sock As Socket, _
Optional ByVal clientDisconnectCallback As TcpClientDisconnectSub = Nothing)
TcpServer = server
' use the provided socket
thisSock = sock
Me.callbackDisconnectSub = clientDisconnectCallback
' start polling for a disconnect
_startPoll()
End Sub
Public ReadOnly Property Ready() As Boolean
Get
Return Not (thisSock Is Nothing)
End Get
End Property
Public ReadOnly Property IsListening() As Boolean
Get
Return Not (thisThread Is Nothing)
End Get
End Property
Public ReadOnly Property IsConnected() As Boolean
Get
If Me.Ready Then
Try
Return Not (thisSock.Available = 0 And _
thisSock.Poll(1, SelectMode.SelectRead))
Catch
Return False
End Try
Else
Return False
End If
End Get
End Property
Public Overloads Sub StartListen(ByVal callbackFunc As TcpClientDataRecvStringFunc)
If thisThread Is Nothing Then
Me.callbackDataRecvStringFunc = callbackFunc
_startListen()
End If
End Sub
Public Overloads Sub StartListen(ByVal callbackFunc As TcpClientDataRecvByteFunc)
If thisThread Is Nothing Then
Me.callbackDataRecvByteFunc = callbackFunc
_startListen()
End If
End Sub
Public Sub StopListen()
If Not (thisThread Is Nothing) Then
thisThread.Abort()
thisThread = Nothing
End If
End Sub
Public Overloads Sub Send(ByVal strData As String)
Dim buff() As Byte = ASCII.GetBytes(strData)
Me.Send(buff)
End Sub
Public Overloads Sub Send(ByVal byteData() As Byte)
If thisSock.Connected Then
' send data to the host
thisSock.Send(byteData, 0, byteData.Length, _
SocketFlags.None)
Else
Throw New Exception("No connection")
End If
End Sub
Public Overloads Function SendAndWait(ByVal strData As String) As String
Dim buff() As Byte = ASCII.GetBytes(strData)
Return ASCII.GetString(Me.SendAndWait(buff))
End Function
Public Overloads Function SendAndWait(ByVal byteData() As Byte) As Byte()
If thisSock.Connected Then
' send data to the host
thisSock.Send(byteData, 0, byteData.Length, _
SocketFlags.None)
Dim rBuff() As Byte = {}
Do ' infinite loop
If thisSock.Available > 0 Then
ReDim rBuff(thisSock.Available - 1)
' receive data from socket
thisSock.Receive(rBuff, 0, _
thisSock.Available, SocketFlags.None)
End If
Loop Until rBuff.Length > 0
Return rBuff
Else
Throw New Exception("No connection")
End If
End Function
Public Overrides Function ToString() As String
If Me.Ready Then
Return thisSock.RemoteEndPoint.ToString
Else
Return MyBase.ToString()
End If
End Function
Public Sub Dispose() Implements IDisposable.Dispose
Try
If Not (pollThread Is Nothing) Then
pollThread.Abort()
pollThread = Nothing
End If
StopListen()
If thisSock.Connected Then thisSock.Disconnect(False)
thisSock.Close()
Catch
End Try
End Sub
Private Sub _startListen()
thisThread = New Thread(AddressOf _threadedListen)
thisThread.Priority = ThreadPriority.BelowNormal
thisThread.IsBackground = True
thisThread.Start(Me)
End Sub
Private Sub _startPoll()
If Not (callbackDisconnectSub Is Nothing) Then
pollThread = New Thread(AddressOf _threadedPoll)
pollThread.Priority = ThreadPriority.BelowNormal
pollThread.IsBackground = True
pollThread.Start(Me)
End If
End Sub
Private Sub _threadedListen(ByVal tcpObject As Object)
Dim thisTcpClient As clsTcpClient = tcpObject
Do ' infinite loop
If thisTcpClient.thisSock.Available > 0 Then
Dim rBuff() As Byte = {}
ReDim rBuff(thisTcpClient.thisSock.Available - 1)
' receive data from socket
thisTcpClient.thisSock.Receive(rBuff)
' invoke callback function
If Not (thisTcpClient.callbackDataRecvStringFunc Is Nothing) Then
Dim strData As String = thisTcpClient.callbackDataRecvStringFunc.Invoke( _
ASCII.GetString(rBuff))
If Not (strData Is Nothing) Then
Dim sBuff() As Byte = ASCII.GetBytes(strData)
' send data back to client
thisTcpClient.thisSock.Send(sBuff, 0, sBuff.Length, _
SocketFlags.None)
End If
ElseIf Not (thisTcpClient.callbackDataRecvByteFunc Is Nothing) Then
Dim byteData() As Byte = thisTcpClient.callbackDataRecvByteFunc.Invoke(rBuff)
If byteData.Length > 0 Then
' send data back to client
thisTcpClient.thisSock.Send(byteData, 0, byteData.Length, _
SocketFlags.None)
End If
End If
End If
' sleep for a duration of time
Thread.Sleep(LOOP_SLEEP_DELAY)
Loop
End Sub
Private Sub _threadedPoll(ByVal tcpObject As Object)
Dim thisTcpClient As clsTcpClient = tcpObject
Do ' infinite loop
If Not thisTcpClient.IsConnected Then
' invoke callback function
If Not (thisTcpClient.callbackDisconnectSub Is Nothing) Then _
thisTcpClient.callbackDisconnectSub.Invoke(thisTcpClient)
Exit Do
End If
' sleep for a duration of time
Thread.Sleep(POLL_SLEEP_DELAY)
Loop
End Sub
End Class