cWinsock TCP Programming Guide
📖 Table of Contents
Overview
TCP (Transmission Control Protocol) is a connection-oriented, reliable transmission protocol, suitable for application scenarios requiring data integrity and ordering guarantee.
TCP Characteristics
- ✅ Connection-oriented: Need to establish connection first
- ✅ Reliable transmission: Guarantees data arrival, ordering, and integrity
- ✅ Flow control: Avoids network congestion
- ✅ Congestion control: Automatically adjusts transmission rate
- ❌ Higher overhead: More protocol overhead compared to UDP
Use Cases
- File transfer
- Chat applications
- Remote control
- Database connection
- Web services
TCP Client Programming
Basic Flow
1. Create cWinsock object
2. Set protocol to TCP
3. Connect to server
4. Wait for Connect event
5. Send/receive data
6. Close connectionComplete Example
vb
' Declare client object
Private WithEvents m_oClient As cWinsock
' Connect button
Private Sub cmdConnect_Click()
On Error GoTo EH
If m_oClient Is Nothing Then
Set m_oClient = New cWinsock
End If
' Set protocol
m_oClient.Protocol = sckTCPProtocol
' Connect to server
m_oClient.Connect txtHost.Text, CLng(txtPort.Text)
' Update UI
cmdConnect.Enabled = False
cmdDisconnect.Enabled = False
lblStatus.Caption = "Connecting..."
Exit Sub
EH:
Debug.Print "Connection error: " & Err.Description
lblStatus.Caption = "Connection failed"
End Sub
' Connection success event
Private Sub m_oClient_Connect(Client As cWinsock)
Debug.Print "Connected to " & Client.RemoteHostIP & ":" & Client.RemotePort
' Update UI
cmdConnect.Enabled = False
cmdDisconnect.Enabled = True
lblStatus.Caption = "Connected"
End Sub
' Disconnect button
Private Sub cmdDisconnect_Click()
If Not m_oClient Is Nothing Then
m_oClient.Close_
End If
' Update UI
cmdConnect.Enabled = True
cmdDisconnect.Enabled = False
lblStatus.Caption = "Disconnected"
End Sub
' Send data button
Private Sub cmdSend_Click()
On Error GoTo EH
If Not m_oClient Is Nothing And m_oClient.State = sckConnected Then
m_oClient.SendData txtSend.Text
Debug.Print "Sent: " & txtSend.Text
' Clear input box
txtSend.Text = ""
Else
MsgBox "Not connected", vbExclamation
End If
Exit Sub
EH:
Debug.Print "Send error: " & Err.Description
End Sub
' Data arrival event
Private Sub m_oClient_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)
Dim sData As String
' Receive data
Client.GetData sData
Debug.Print "Received data (" & bytesTotal & " bytes): " & sData
' Display on UI
txtReceive.SelStart = Len(txtReceive.Text)
txtReceive.SelText = sData & vbCrLf
txtReceive.SelStart = Len(txtReceive.Text)
End Sub
' Connection closed event
Private Sub m_oClient_CloseEvent(Client As cWinsock)
Debug.Print "Connection closed"
' Update UI
cmdConnect.Enabled = True
cmdDisconnect.Enabled = False
lblStatus.Caption = "Connection closed"
End Sub
' Error event
Private Sub m_oClient_Error(Client As cWinsock, ByVal Number As Long, Description As String, ByVal Scode As Long)
Debug.Print "Error [" & Number & "]: " & Description
' Update UI
lblStatus.Caption = "Error: " & Description
End Sub
' Form unload
Private Sub Form_Unload(Cancel As Integer)
On Error Resume Next
m_oClient.Close_
End SubTCP Server Programming
Basic Flow
1. Create cWinsock object
2. Set protocol to TCP
3. Listen on port
4. Wait for ConnectionRequest event
5. Accept or reject connection
6. Process client data via DataArrival
7. Clean up when client disconnectsComplete Example
vb
' Declare server object
Private WithEvents m_oServer As cWinsock
' Start server button
Private Sub cmdStart_Click()
On Error GoTo EH
If m_oServer Is Nothing Then
Set m_oServer = New cWinsock
End If
' Set protocol
m_oServer.Protocol = sckTCPProtocol
' Start listening
m_oServer.Listen CLng(txtPort.Text)
Debug.Print "Server started, listening on port: " & m_oServer.LocalPort
' Update UI
cmdStart.Enabled = False
cmdStop.Enabled = True
lblStatus.Caption = "Listening..."
lblClientCount.Caption = "0"
Exit Sub
EH:
Debug.Print "Failed to start server: " & Err.Description
MsgBox "Cannot start server: " & Err.Description, vbExclamation
End Sub
' Stop server button
Private Sub cmdStop_Click()
On Error Resume Next
If Not m_oServer Is Nothing Then
m_oServer.Close_
End If
Debug.Print "Server stopped"
' Update UI
cmdStart.Enabled = True
cmdStop.Enabled = False
lblStatus.Caption = "Stopped"
lstClients.Clear
End Sub
' New connection request event
Private Sub m_oServer_ConnectionRequest(Client As cWinsock, ByRef DisConnect As Boolean)
Debug.Print "New client connection: " & Client.RemoteHostIP & ":" & Client.RemotePort
' Check connection count limit
If m_oServer.ClientCount >= 100 Then
Debug.Print "Maximum connections reached, rejecting connection"
DisConnect = True
Exit Sub
End If
' IP blacklist check
If IsInBlacklist(Client.RemoteHostIP) Then
Debug.Print "IP in blacklist, rejecting connection: " & Client.RemoteHostIP
DisConnect = True
Exit Sub
End If
' Accept connection (DisConnect = False)
Debug.Print "Accept connection: " & Client.Tag
' Update client list
UpdateClientList
End Sub
' Data arrival event (all client data triggered through this event)
Private Sub m_oServer_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)
Dim sData As String
' Receive data
Client.GetData sData
Debug.Print "Data from " & Client.Tag & " (" & Client.RemoteHostIP & "): " & sData
' Display in log
LogMessage Client.Tag & ": " & sData
' Echo to client
Client.SendData "Echo: " & sData
End Sub
' Connection closed event
Private Sub m_oServer_CloseEvent(Client As cWinsock)
Debug.Print "Client " & Client.Tag & " disconnected"
' Update client list
UpdateClientList
End Sub
' Error event
Private Sub m_oServer_Error(Client As cWinsock, ByVal Number As Long, Description As String, ByVal Scode As Long)
Debug.Print "Error [" & Number & "]: " & Description
If Client.IsServer Then
' Server error
LogMessage "Server error: " & Description
Else
' Client error
LogMessage "Client " & Client.Tag & " error: " & Description
End If
End Sub
' Update client list
Private Sub UpdateClientList()
lstClients.Clear
lblClientCount.Caption = m_oServer.ClientCount
Dim oClient As cWinsock
For Each oClient In m_oServer.Clients
lstClients.AddItem oClient.Tag & " - " & oClient.RemoteHostIP & ":" & oClient.RemotePort
Next
End Sub
' Add log
Private Sub LogMessage(ByVal sMsg As String)
txtLog.SelStart = Len(txtLog.Text)
txtLog.SelText = Format$(Now, "hh:mm:ss") & " - " & sMsg & vbCrLf
txtLog.SelStart = Len(txtLog.Text)
End Sub
' Form unload
Private Sub Form_Unload(Cancel As Integer)
On Error Resume Next
m_oServer.Close_
End Sub
' Blacklist check
Private Function IsInBlacklist(ByVal sIP As String) As Boolean
' Load blacklist from config file or database
' Simplified demonstration here
IsInBlacklist = False
End FunctionAdvanced Features
🔄 Heartbeat Detection
vb
' Server-side heartbeat detection
Private Const HEARTBEAT_INTERVAL As Long = 30 ' 30 seconds
Private Sub tmrHeartbeat_Timer()
Dim oClient As cWinsock
Dim tSession As tSessionData
For Each oClient In m_oServer.Clients
tSession = oClient.UserData
' Check if timeout
If DateDiff("s", tSession.LastActivity, Now) > HEARTBEAT_INTERVAL Then
Debug.Print "Client " & oClient.Tag & " heartbeat timeout"
oClient.Close_
Else
' Send heartbeat request
oClient.SendData "PING"
End If
Next
End Sub
' Client response to heartbeat
Private Sub m_oClient_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)
Dim sData As String
Client.GetData sData
If sData = "PING" Then
' Respond to heartbeat
Client.SendData "PONG"
ElseIf sData = "PONG" Then
Debug.Print "Received heartbeat response"
Else
' Process other data
ProcessData sData
End If
End Sub📦 Protocol Encapsulation
vb
' Define protocol header
Private Type tPacketHeader
Magic As Long ' Magic number: &H12345678
Length As Long ' Data length
Type As Long ' Data type: 1=text, 2=binary
Checksum As Long ' Checksum
End Type
' Send structured data
Private Sub SendPacket(ByVal oSocket As cWinsock, ByVal eType As Long, ByVal baData() As Byte)
Dim tHeader As tPacketHeader
Dim baPacket() As Byte
Dim lOffset As Long
' Fill header
tHeader.Magic = &H12345678
tHeader.Length = UBound(baData) + 1
tHeader.Type = eType
tHeader.Checksum = CalculateChecksum(baData)
' Construct complete packet
ReDim baPacket(0 To Len(tHeader) + tHeader.Length - 1) As Byte
' Copy header
CopyMemory baPacket(0), tHeader, Len(tHeader)
' Copy data body
lOffset = Len(tHeader)
CopyMemory baPacket(lOffset), baData(0), tHeader.Length
' Send
oSocket.SendData baPacket
End Sub
' Receive structured data
Private Sub m_oServer_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)
Dim tHeader As tPacketHeader
Dim baData() As Byte
' Read header first
Client.GetData tHeader
' Verify magic number
If tHeader.Magic <> &H12345678 Then
Debug.Print "Invalid packet"
Exit Sub
End If
' Verify checksum
ReDim baData(0 To tHeader.Length - 1) As Byte
Client.GetData baData
If CalculateChecksum(baData) <> tHeader.Checksum Then
Debug.Print "Checksum error"
Exit Sub
End If
' Process data by type
Select Case tHeader.Type
Case 1 ' Text
Dim sText As String
sText = BytesToString(baData)
Debug.Print "Text data: " & sText
Case 2 ' Binary
Debug.Print "Binary data: " & tHeader.Length & " bytes"
End Select
End Sub🔄 Auto Reconnect
vb
' Auto reconnect client
Private WithEvents m_oClient As cWinsock
Private m_bAutoReconnect As Boolean
Private m_lReconnectInterval As Long
Private Sub StartClient()
Set m_oClient = New cWinsock
m_oClient.Protocol = sckTCPProtocol
m_bAutoReconnect = True
m_lReconnectInterval = 5 ' 5 seconds
ConnectToServer
End Sub
Private Sub ConnectToServer()
On Error GoTo EH
m_oClient.Connect "127.0.0.1", 8080
Debug.Print "Connecting..."
Exit Sub
EH:
Debug.Print "Connection failed: " & Err.Description
If m_bAutoReconnect Then
Debug.Print "Reconnecting in " & m_lReconnectInterval & " seconds..."
tmrReconnect.Interval = m_lReconnectInterval * 1000
tmrReconnect.Enabled = True
End If
End Sub
Private Sub m_oClient_CloseEvent(Client As cWinsock)
Debug.Print "Connection closed"
If m_bAutoReconnect Then
Debug.Print "Reconnecting in " & m_lReconnectInterval & " seconds..."
tmrReconnect.Interval = m_lReconnectInterval * 1000
tmrReconnect.Enabled = True
End If
End Sub
Private Sub tmrReconnect_Timer()
tmrReconnect.Enabled = False
ConnectToServer
End Sub🚦 Flow Control
vb
' File transfer with flow control
Private m_oClient As cWinsock
Private m_lChunkSize As Long
Private m_bSending As Boolean
Private Sub SendFile(ByVal sFilePath As String)
Dim iFileNum As Integer
Dim baChunk() As Byte
Dim lFileSize As Long
Dim lSent As Long
iFileNum = FreeFile
Open sFilePath For Binary As #iFileNum
lFileSize = LOF(iFileNum)
m_lChunkSize = 8192 ' 8KB per chunk
lSent = 0
m_bSending = True
Do While lSent < lFileSize And m_bSending
' Read data chunk
ReDim baChunk(0 To m_lChunkSize - 1) As Byte
Get #iFileNum, , baChunk
' Send
m_oClient.SendData baChunk
lSent = lSent + m_lChunkSize
' Update progress
UpdateProgress lSent, lFileSize
' Wait for send completion
Do While m_bSending
DoEvents
If Not m_oClient.State = sckConnected Then Exit Do
Loop
If Not m_oClient.State = sckConnected Then Exit Do
Loop
Close #iFileNum
Debug.Print "File transfer completed"
End Sub
Private Sub m_oClient_SendComplete(Client As cWinsock)
m_bSending = False
End SubCommon Issues
❓ Issue 1: Connection Refused
Symptom: Error 10061 - Connection refused
Cause:
- Server not started
- Port blocked by firewall
- Wrong IP address or port
Solution:
vb
' Check if server is running
If m_oServer.State <> sckListening Then
MsgBox "Server not started", vbExclamation
Exit Sub
End If
' Check port
If Not IsPortOpen(txtPort.Text) Then
MsgBox "Port " & txtPort.Text & " not open", vbExclamation
End If❓ Issue 2: Connection Timeout
Symptom: Error 10060 - Connection timeout
Cause:
- Network unreachable
- Server slow to respond
- Firewall blocking
Solution:
vb
' Add retry mechanism
Private Function ConnectWithRetry(ByVal sHost As String, ByVal lPort As Long, ByVal lRetries As Long) As Boolean
Dim i As Long
For i = 1 To lRetries
On Error Resume Next
m_oClient.Connect sHost, lPort
If Err.Number = 0 Then
ConnectWithRetry = True
Exit Function
End If
Debug.Print "Retry " & i & "/" & lRetries & " failed: " & Err.Description
' Wait before retry
Sleep 2000
Next
ConnectWithRetry = False
End Function❓ Issue 3: Data Loss
Symptom: Sent data not received by peer
Cause:
- Network issues
- Buffer overflow
- Peer not reading correctly
Solution:
vb
' Confirm peer received
Private Sub SendWithAck(ByVal sData As String)
Dim sAck As String
' Send data
m_oClient.SendData "DATA:" & sData
' Wait for acknowledgment
sAck = WaitForAck(5000) ' 5 second timeout
If sAck = "ACK" Then
Debug.Print "Peer confirmed receipt"
Else
Debug.Print "No acknowledgment, resending"
m_oClient.SendData "DATA:" & sData
End If
End SubLast Updated: 2026-01-09