- Contents in this wiki are for entertainment purposes only
Robust Winsock VB6 Class
Jump to navigation
Jump to search
Option Explicit
' RobustWinsock Class
' A robust VB6 winsock implementation designed to handle large data transfers,
' connection failures, and error recovery.
'
' Features:
' - Automatic reconnection on failure
' - Chunked data transfer for large files
' - Timeout handling
' - CRC checking for data integrity
' - Session management
' - Event-based architecture
' - Comprehensive error handling
' - Buffer management for large transfers
' Constants for socket states
Private Const SOCKET_CLOSED = 0
Private Const SOCKET_OPEN = 1
Private Const SOCKET_LISTENING = 2
Private Const SOCKET_CONNECTION_PENDING = 3
Private Const SOCKET_RESOLVING_HOST = 4
Private Const SOCKET_HOST_RESOLVED = 5
Private Const SOCKET_CONNECTING = 6
Private Const SOCKET_CONNECTED = 7
Private Const SOCKET_CLOSING = 8
Private Const SOCKET_ERROR = 9
' Constants for CRC calculation
Private Const CRC32_POLYNOMIAL = &HEDB88320
' Constants for error handling
Private Const ERR_WINSOCK_BASE = 10000
Private Const ERR_CONNECTION_TIMEOUT = ERR_WINSOCK_BASE + 1
Private Const ERR_CONNECTION_RESET = ERR_WINSOCK_BASE + 2
Private Const ERR_DATA_INTEGRITY = ERR_WINSOCK_BASE + 3
Private Const ERR_BUFFER_OVERFLOW = ERR_WINSOCK_BASE + 4
' Constants for data transfer
Private Const DEFAULT_BUFFER_SIZE = 8192 ' 8KB default buffer
Private Const MAX_BUFFER_SIZE = 1048576 ' 1MB max buffer
Private Const DEFAULT_TIMEOUT = 30000 ' 30 seconds
Private Const DEFAULT_RETRY_COUNT = 3 ' Default number of retries
Private Const DEFAULT_HEARTBEAT_INTERVAL = 5000 ' 5 seconds
' Member variables
Private m_Winsock As Winsock ' The actual Winsock control
Private m_BufferSize As Long ' Size of the buffer
Private m_SendBuffer() As Byte ' Buffer for sending data
Private m_ReceiveBuffer() As Byte ' Buffer for receiving data
Private m_SendBufferLength As Long ' Current length of send buffer
Private m_ReceiveBufferLength As Long ' Current length of receive buffer
Private m_Timeout As Long ' Timeout in milliseconds
Private m_RetryCount As Integer ' Number of retries
Private m_CurrentRetry As Integer ' Current retry count
Private m_RemoteHost As String ' Remote host name or IP
Private m_RemotePort As Long ' Remote port
Private m_LocalPort As Long ' Local port
Private m_Connected As Boolean ' Connection state
Private m_LastError As Long ' Last error code
Private m_LastErrorMessage As String ' Last error message
Private m_AutoReconnect As Boolean ' Auto reconnect flag
Private m_HeartbeatTimer As Timer ' Timer for heartbeats
Private m_HeartbeatInterval As Long ' Heartbeat interval
Private m_TransferInProgress As Boolean ' Flag for transfer in progress
Private m_TotalBytesSent As Long ' Total bytes sent in current transfer
Private m_TotalBytesReceived As Long ' Total bytes received in current transfer
Private m_ConnectionTimer As Timer ' Timer for connection timeout
Private m_SessionID As String ' Unique session identifier
Private m_CRCTable(0 To 255) As Long ' Table for CRC calculation
Private m_TransferID As Long ' Current transfer ID
Private m_ChunkSize As Long ' Size of data chunks
Private m_PacketSequence As Long ' Packet sequence number
' Event declarations
Public Event Connected()
Public Event Disconnected()
Public Event DataArrival(ByVal bytesTotal As Long)
Public Event SendComplete()
Public Event Error(ByVal Number As Long, ByVal Description As String)
Public Event ConnectionRequest(ByVal requestID As Long)
Public Event ProgressUpdate(ByVal bytesSent As Long, ByVal bytesTotal As Long)
Public Event TransferComplete(ByVal transferID As Long, ByVal success As Boolean)
Public Event Timeout()
Public Event Reconnecting(ByVal attemptNumber As Integer)
' Class initialization
Private Sub Class_Initialize()
' Initialize default values
m_BufferSize = DEFAULT_BUFFER_SIZE
m_Timeout = DEFAULT_TIMEOUT
m_RetryCount = DEFAULT_RETRY_COUNT
m_CurrentRetry = 0
m_Connected = False
m_AutoReconnect = True
m_HeartbeatInterval = DEFAULT_HEARTBEAT_INTERVAL
m_TransferInProgress = False
m_TotalBytesSent = 0
m_TotalBytesReceived = 0
m_ChunkSize = DEFAULT_BUFFER_SIZE
m_PacketSequence = 0
' Initialize buffers
ReDim m_SendBuffer(0 To m_BufferSize - 1)
ReDim m_ReceiveBuffer(0 To m_BufferSize - 1)
' Create a unique session ID
m_SessionID = GenerateSessionID()
' Initialize CRC table
InitializeCRCTable
' Create the Winsock control
Set m_Winsock = New Winsock
' Set up timers
Set m_HeartbeatTimer = New Timer
m_HeartbeatTimer.Interval = m_HeartbeatInterval
m_HeartbeatTimer.Enabled = False
Set m_ConnectionTimer = New Timer
m_ConnectionTimer.Interval = m_Timeout
m_ConnectionTimer.Enabled = False
End Sub
' Class termination
Private Sub Class_Terminate()
' Clean up
If m_Connected Then
DisconnectSocket
End If
' Stop timers
m_HeartbeatTimer.Enabled = False
m_ConnectionTimer.Enabled = False
' Clean up objects
Set m_Winsock = Nothing
Set m_HeartbeatTimer = Nothing
Set m_ConnectionTimer = Nothing
End Sub
' Initialize the CRC table for data integrity checks
Private Sub InitializeCRCTable()
Dim i As Long, j As Long, crc As Long
For i = 0 To 255
crc = i
For j = 0 To 7
If (crc And 1) Then
crc = (crc \ 2) Xor CRC32_POLYNOMIAL
Else
crc = crc \ 2
End If
Next j
m_CRCTable(i) = crc
Next i
End Sub
' Calculate CRC32 for data integrity
Private Function CalculateCRC32(data() As Byte, ByVal length As Long) As Long
Dim crc As Long, i As Long
crc = &HFFFFFFFF
For i = 0 To length - 1
crc = ((crc \ 256) And &HFFFFFF) Xor m_CRCTable((crc And &HFF) Xor data(i))
Next i
CalculateCRC32 = Not crc
End Function
' Generate a unique session ID
Private Function GenerateSessionID() As String
Dim guid As String
guid = Format$(Now, "yyyymmddhhnnss") & Format$(Timer, "000000") & Format$(Rnd() * 1000000, "000000")
GenerateSessionID = guid
End Function
' Connect to a remote host
Public Function Connect(ByVal remoteHost As String, ByVal remotePort As Long) As Boolean
On Error GoTo ErrorHandler
' Store connection parameters
m_RemoteHost = remoteHost
m_RemotePort = remotePort
' Reset counters
m_CurrentRetry = 0
m_TotalBytesSent = 0
m_TotalBytesReceived = 0
' Attempt to connect
AttemptConnection
' Start connection timeout timer
m_ConnectionTimer.Enabled = True
Connect = True
Exit Function
ErrorHandler:
m_LastError = Err.Number
m_LastErrorMessage = Err.Description
RaiseEvent Error(m_LastError, m_LastErrorMessage)
Connect = False
End Function
' Internal connection attempt
Private Sub AttemptConnection()
On Error GoTo ErrorHandler
' Close any existing connection
If m_Connected Then
DisconnectSocket
End If
' Attempt to connect
m_Winsock.Connect m_RemoteHost, m_RemotePort
Exit Sub
ErrorHandler:
m_LastError = Err.Number
m_LastErrorMessage = Err.Description
' Handle connection failure with retry
If m_AutoReconnect And m_CurrentRetry < m_RetryCount Then
m_CurrentRetry = m_CurrentRetry + 1
RaiseEvent Reconnecting(m_CurrentRetry)
' Wait a bit before retrying (exponential backoff)
Dim waitTime As Long
waitTime = 1000 * (2 ^ m_CurrentRetry)
' Use a timer to retry
Dim retryTimer As Timer
Set retryTimer = New Timer
retryTimer.Interval = waitTime
retryTimer.Enabled = True
' Retry after wait
AttemptConnection
Else
' Failed after all retries
RaiseEvent Error(m_LastError, m_LastErrorMessage)
End If
End Sub
' Listen for incoming connections
Public Function Listen(ByVal localPort As Long) As Boolean
On Error GoTo ErrorHandler
' Store local port
m_LocalPort = localPort
' Close any existing connection
If m_Connected Then
DisconnectSocket
End If
' Start listening
m_Winsock.LocalPort = localPort
m_Winsock.Listen
Listen = True
Exit Function
ErrorHandler:
m_LastError = Err.Number
m_LastErrorMessage = Err.Description
RaiseEvent Error(m_LastError, m_LastErrorMessage)
Listen = False
End Function
' Accept an incoming connection
Public Function Accept(ByVal requestID As Long) As Boolean
On Error GoTo ErrorHandler
' Accept the connection
m_Winsock.Accept requestID
m_Connected = True
' Start heartbeat timer
m_HeartbeatTimer.Enabled = True
' Stop connection timeout timer
m_ConnectionTimer.Enabled = False
' Raise connected event
RaiseEvent Connected
Accept = True
Exit Function
ErrorHandler:
m_LastError = Err.Number
m_LastErrorMessage = Err.Description
RaiseEvent Error(m_LastError, m_LastErrorMessage)
Accept = False
End Function
' Disconnect from the remote host
Public Sub Disconnect()
On Error Resume Next
DisconnectSocket
' Raise disconnected event
RaiseEvent Disconnected
End Sub
' Internal disconnect method
Private Sub DisconnectSocket()
On Error Resume Next
' Close the socket
If m_Winsock.State <> SOCKET_CLOSED Then
m_Winsock.Close
End If
' Reset connection state
m_Connected = False
' Stop timers
m_HeartbeatTimer.Enabled = False
m_ConnectionTimer.Enabled = False
' Reset buffers
m_SendBufferLength = 0
m_ReceiveBufferLength = 0
m_TransferInProgress = False
End Sub
' Send data over the connection
Public Function SendData(data() As Byte, ByVal length As Long) As Boolean
On Error GoTo ErrorHandler
' Check if connected
If Not m_Connected Then
m_LastError = ERR_WINSOCK_BASE
m_LastErrorMessage = "Not connected"
RaiseEvent Error(m_LastError, m_LastErrorMessage)
SendData = False
Exit Function
End If
' Initialize transfer
m_TransferInProgress = True
m_TotalBytesSent = 0
m_TransferID = CLng(Timer * 1000) ' Create a unique transfer ID
' Send data in chunks for large transfers
Dim remainingBytes As Long, currentChunk As Long, i As Long
Dim sendBuffer() As Byte, headerBuffer(0 To 15) As Byte
Dim crc As Long
remainingBytes = length
i = 0
Do While remainingBytes > 0
' Determine chunk size
currentChunk = IIf(remainingBytes > m_ChunkSize, m_ChunkSize, remainingBytes)
' Prepare chunk buffer
ReDim sendBuffer(0 To currentChunk - 1)
' Copy data to chunk buffer
CopyMemory sendBuffer(0), data(i), currentChunk
' Calculate CRC for this chunk
crc = CalculateCRC32(sendBuffer, currentChunk)
' Create packet header
' Format: [SessionID(8)][TransferID(4)][SequenceNumber(2)][Length(2)][CRC(4)]
m_PacketSequence = m_PacketSequence + 1
' Prepare packet header
ReDim headerBuffer(0 To 19)
CopyMemory headerBuffer(0), CLng(m_TransferID), 4
CopyMemory headerBuffer(4), CInt(m_PacketSequence), 2
CopyMemory headerBuffer(6), CInt(currentChunk), 2
CopyMemory headerBuffer(8), CLng(crc), 4
' Send header
m_Winsock.SendData headerBuffer
' Small delay to ensure header is sent
Sleep 10
' Send data chunk
m_Winsock.SendData sendBuffer
' Update counters
m_TotalBytesSent = m_TotalBytesSent + currentChunk
remainingBytes = remainingBytes - currentChunk
i = i + currentChunk
' Raise progress event
RaiseEvent ProgressUpdate(m_TotalBytesSent, length)
' Small delay between chunks to prevent buffer overflow
If remainingBytes > 0 Then Sleep 50
Loop
SendData = True
Exit Function
ErrorHandler:
m_LastError = Err.Number
m_LastErrorMessage = Err.Description
RaiseEvent Error(m_LastError, m_LastErrorMessage)
m_TransferInProgress = False
SendData = False
End Function
' Send a string over the connection
Public Function SendString(ByVal strData As String) As Boolean
On Error GoTo ErrorHandler
' Convert string to byte array
Dim dataBytes() As Byte
Dim length As Long
length = Len(strData)
ReDim dataBytes(0 To length - 1)
' Copy string to byte array
CopyMemory dataBytes(0), ByVal strData, length
' Send the data
SendString = SendData(dataBytes, length)
Exit Function
ErrorHandler:
m_LastError = Err.Number
m_LastErrorMessage = Err.Description
RaiseEvent Error(m_LastError, m_LastErrorMessage)
SendString = False
End Function
' Send a file over the connection
Public Function SendFile(ByVal filePath As String) As Boolean
On Error GoTo ErrorHandler
' Check if file exists
If Not FileExists(filePath) Then
m_LastError = ERR_WINSOCK_BASE
m_LastErrorMessage = "File not found: " & filePath
RaiseEvent Error(m_LastError, m_LastErrorMessage)
SendFile = False
Exit Function
End If
' Open the file
Dim fileNum As Integer
Dim fileLength As Long
Dim buffer() As Byte
Dim bytesRead As Long
fileNum = FreeFile
' Get file size
fileLength = FileLen(filePath)
' Prepare buffer for file data
ReDim buffer(0 To fileLength - 1)
' Read file into buffer
Open filePath For Binary Access Read As #fileNum
Get #fileNum, , buffer
Close #fileNum
' Send the file data
SendFile = SendData(buffer, fileLength)
Exit Function
ErrorHandler:
' Close file if open
If fileNum > 0 Then
Close #fileNum
End If
m_LastError = Err.Number
m_LastErrorMessage = Err.Description
RaiseEvent Error(m_LastError, m_LastErrorMessage)
SendFile = False
End Function
' Check if a file exists
Private Function FileExists(ByVal filePath As String) As Boolean
On Error Resume Next
FileExists = (Dir(filePath) <> "")
End Function
' Get data from the receive buffer
Public Function GetData(ByRef data() As Byte, ByVal maxLength As Long) As Long
On Error GoTo ErrorHandler
' Check if there's data in the buffer
If m_ReceiveBufferLength = 0 Then
GetData = 0
Exit Function
End If
' Determine how much data to copy
Dim copyLength As Long
copyLength = IIf(m_ReceiveBufferLength > maxLength, maxLength, m_ReceiveBufferLength)
' Resize the output buffer
ReDim data(0 To copyLength - 1)
' Copy data from receive buffer
CopyMemory data(0), m_ReceiveBuffer(0), copyLength
' Shift remaining data in buffer
If copyLength < m_ReceiveBufferLength Then
CopyMemory m_ReceiveBuffer(0), m_ReceiveBuffer(copyLength), m_ReceiveBufferLength - copyLength
End If
' Update buffer length
m_ReceiveBufferLength = m_ReceiveBufferLength - copyLength
GetData = copyLength
Exit Function
ErrorHandler:
m_LastError = Err.Number
m_LastErrorMessage = Err.Description
RaiseEvent Error(m_LastError, m_LastErrorMessage)
GetData = 0
End Function
' Get all available data as a string
Public Function GetString() As String
On Error GoTo ErrorHandler
' Check if there's data in the buffer
If m_ReceiveBufferLength = 0 Then
GetString = ""
Exit Function
End If
' Convert buffer to string
Dim strData As String
strData = Space(m_ReceiveBufferLength)
' Copy data to string
CopyMemory ByVal strData, m_ReceiveBuffer(0), m_ReceiveBufferLength
' Reset buffer
m_ReceiveBufferLength = 0
GetString = strData
Exit Function
ErrorHandler:
m_LastError = Err.Number
m_LastErrorMessage = Err.Description
RaiseEvent Error(m_LastError, m_LastErrorMessage)
GetString = ""
End Function
' Save received data to a file
Public Function SaveToFile(ByVal filePath As String) As Boolean
On Error GoTo ErrorHandler
' Check if there's data in the buffer
If m_ReceiveBufferLength = 0 Then
SaveToFile = False
Exit Function
End If
' Open the file
Dim fileNum As Integer
fileNum = FreeFile
' Write buffer to file
Open filePath For Binary Access Write As #fileNum
Put #fileNum, , m_ReceiveBuffer
Close #fileNum
' Reset buffer
m_ReceiveBufferLength = 0
SaveToFile = True
Exit Function
ErrorHandler:
' Close file if open
If fileNum > 0 Then
Close #fileNum
End If
m_LastError = Err.Number
m_LastErrorMessage = Err.Description
RaiseEvent Error(m_LastError, m_LastErrorMessage)
SaveToFile = False
End Function
' Winsock event handlers
Private Sub m_Winsock_Connect()
' Connection established
m_Connected = True
' Reset retry counter
m_CurrentRetry = 0
' Stop connection timeout timer
m_ConnectionTimer.Enabled = False
' Start heartbeat timer
m_HeartbeatTimer.Enabled = True
' Raise connected event
RaiseEvent Connected
End Sub
Private Sub m_Winsock_Close()
' Connection closed
m_Connected = False
' Stop timers
m_HeartbeatTimer.Enabled = False
m_ConnectionTimer.Enabled = False
' Reset transfer state
m_TransferInProgress = False
' Raise disconnected event
RaiseEvent Disconnected
' Auto reconnect if enabled
If m_AutoReconnect Then
AttemptConnection
End If
End Sub
Private Sub m_Winsock_DataArrival(ByVal bytesTotal As Long)
On Error GoTo ErrorHandler
' Resize buffer if needed
If m_ReceiveBufferLength + bytesTotal > UBound(m_ReceiveBuffer) + 1 Then
' Buffer overflow, resize
ReDim Preserve m_ReceiveBuffer(0 To m_ReceiveBufferLength + bytesTotal - 1)
End If
' Get data from winsock
Dim tempBuffer() As Byte
ReDim tempBuffer(0 To bytesTotal - 1)
m_Winsock.GetData tempBuffer
' Process the packet
' Check for header
If bytesTotal >= 12 Then
' Extract header information
Dim transferID As Long, sequence As Integer, length As Integer, crc As Long
CopyMemory transferID, tempBuffer(0), 4
CopyMemory sequence, tempBuffer(4), 2
CopyMemory length, tempBuffer(6), 2
CopyMemory crc, tempBuffer(8), 4
' Verify this is a data packet with a valid header
If bytesTotal >= 12 + length Then
' Calculate CRC of the data
Dim dataCRC As Long
' Create temp buffer for CRC calculation
Dim crcBuffer() As Byte
ReDim crcBuffer(0 To length - 1)
' Copy data portion
CopyMemory crcBuffer(0), tempBuffer(12), length
' Calculate CRC
dataCRC = CalculateCRC32(crcBuffer, length)
' Verify CRC
If dataCRC = crc Then
' Valid packet, copy to receive buffer
CopyMemory m_ReceiveBuffer(m_ReceiveBufferLength), crcBuffer(0), length
m_ReceiveBufferLength = m_ReceiveBufferLength + length
' Update total received
m_TotalBytesReceived = m_TotalBytesReceived + length
' Raise data arrival event
RaiseEvent DataArrival(length)
Else
' CRC mismatch, data corruption
m_LastError = ERR_DATA_INTEGRITY
m_LastErrorMessage = "Data integrity check failed"
RaiseEvent Error(m_LastError, m_LastErrorMessage)
End If
Else
' Not a valid packet, just append to buffer
CopyMemory m_ReceiveBuffer(m_ReceiveBufferLength), tempBuffer(0), bytesTotal
m_ReceiveBufferLength = m_ReceiveBufferLength + bytesTotal
' Update total received
m_TotalBytesReceived = m_TotalBytesReceived + bytesTotal
' Raise data arrival event
RaiseEvent DataArrival(bytesTotal)
End If
Else
' Not enough data for header, just append to buffer
CopyMemory m_ReceiveBuffer(m_ReceiveBufferLength), tempBuffer(0), bytesTotal
m_ReceiveBufferLength = m_ReceiveBufferLength + bytesTotal
' Update total received
m_TotalBytesReceived = m_TotalBytesReceived + bytesTotal
' Raise data arrival event
RaiseEvent DataArrival(bytesTotal)
End If
Exit Sub
ErrorHandler:
m_LastError = Err.Number
m_LastErrorMessage = Err.Description
RaiseEvent Error(m_LastError, m_LastErrorMessage)
End Sub
Private Sub m_Winsock_Error(ByVal Number As Integer, ByVal Description As String, ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, ByVal CancelDisplay As Boolean)
' Store error information
m_LastError = Number
m_LastErrorMessage = Description
' Handle connection reset errors with retry
If Number = 10054 Then ' Connection reset by peer
m_Connected = False
' Stop timers
m_HeartbeatTimer.Enabled = False
m_ConnectionTimer.Enabled = False
' Reset transfer state
m_TransferInProgress = False
' Auto reconnect if enabled
If m_AutoReconnect Then
AttemptConnection
End If
End If
' Raise error event
RaiseEvent Error(Number, Description)
End Sub
Private Sub m_Winsock_ConnectionRequest(ByVal requestID As Long)
' Forward connection request event
RaiseEvent ConnectionRequest(requestID)
End Sub
Private Sub m_Winsock_SendComplete()
' Forward send complete event
RaiseEvent SendComplete
' Check if transfer is complete
If m_TransferInProgress And m_TotalBytesSent > 0 Then
m_TransferInProgress = False
RaiseEvent TransferComplete(m_TransferID, True)
End If
End Sub
' Timer event handlers
Private Sub m_HeartbeatTimer_Timer()
On Error Resume Next
' Send heartbeat packet to keep connection alive
If m_Connected Then
' Create a small heartbeat packet
Dim heartbeat(0 To 3) As Byte
heartbeat(0) = &HFF
heartbeat(1) = &HFF
heartbeat(2) = &HFF
heartbeat(3) = &HFF
' Send heartbeat
m_Winsock.SendData heartbeat
End If
End Sub
Private Sub m_ConnectionTimer_Timer()
' Connection timeout
m_ConnectionTimer.Enabled = False
' Check if still not connected
If Not m_Connected Then
' Stop connection attempt
On Error Resume Next
m_Winsock.Close
' Set error
m_LastError = ERR_CONNECTION_TIMEOUT
m_LastErrorMessage = "Connection timeout"
' Raise timeout event
RaiseEvent Timeout
' Try to reconnect if auto reconnect is enabled
If m_AutoReconnect And m_CurrentRetry < m_RetryCount Then
AttemptConnection
Else
' Raise error event
RaiseEvent Error(m_LastError, m_LastErrorMessage)
End If
End If
End Sub
' Property procedures
Public Property Get BufferSize() As Long
BufferSize = m_BufferSize
End Property
Public Property Let BufferSize(ByVal value As Long)
' Ensure buffer size is within limits
If value > 0 And value <= MAX_BUFFER_SIZE Then
m_BufferSize = value
' Resize buffers
ReDim Preserve m_SendBuffer(0 To m_BufferSize - 1)
ReDim Preserve m_ReceiveBuffer(0 To m_BufferSize - 1)
End If
End Property
Public Property Get ChunkSize() As Long
ChunkSize = m_ChunkSize
End Property
Public Property Let ChunkSize(ByVal value As Long)
' Ensure chunk size is reasonable
If value > 0 And value <= MAX_BUFFER_SIZE Then
m_ChunkSize = value
End If
End Property
Public Property Get Timeout() As Long
Timeout = m_Timeout
End Property
Public Property Let Timeout(ByVal value As Long)
If value > 0 Then
m_Timeout = value
m_ConnectionTimer.Interval = value
End If
End Property
Public Property Get RetryCount() As Integer
RetryCount = m_RetryCount
End Property
Public Property Let RetryCount(ByVal value As Integer)
If value >= 0 Then
m_RetryCount = value
End If
End Property
Public Property Get AutoReconnect() As Boolean
AutoReconnect = m_AutoReconnect
End Property
Public Property Let AutoReconnect(ByVal value As Boolean)
m_AutoReconnect = value
End Property
Public Property Get HeartbeatInterval() As Long
HeartbeatInterval = m_HeartbeatInterval
End Property
Public Property Let HeartbeatInterval(ByVal value As Long)
If value > 0 Then
m_HeartbeatInterval = value
m_HeartbeatTimer.Interval = value
End If
End Property
Public Property Get SessionID() As String
SessionID = m_SessionID
End Property
Public Property Get RemoteHost() As String
RemoteHost = m_RemoteHost
End Property
Public Property Get RemotePort() As Long
RemotePort = m_RemotePort
End Property
Public Property Get LocalPort() As Long
LocalPort = m_LocalPort
End Property
Public Property Let LocalPort(ByVal value As Long)
If value > 0 Then
m_LocalPort = value
End If
End Property
Public Property Get IsConnected() As Boolean
IsConnected = m_Connected
End Property
Public Property Get LastError() As Long
LastError = m_LastError
End Property
Public Property Get LastErrorMessage() As String
LastErrorMessage = m_LastErrorMessage
End Property
Public Property Get BytesSent() As Long
BytesSent = m_TotalBytesSent
End Property
Public Property Get BytesReceived() As Long
BytesReceived = m_TotalBytesReceived
End Property
Public Property Get State() As Integer
If Not m_Winsock Is Nothing Then
State = m_Winsock.State
Else
State = SOCKET_CLOSED
End If
End Property
' Utility function to copy memory (needs a declare statement in a module)
' Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
' Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)