Projects

Find all our projects in development below.
All source code is GNU General Public License (GPL)

javaSpy

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

Download clsTcpClient.vb

Back to file list


Back to project page