cWinsock TCP Programming Guide
📖 Table of Contents
Overview
TCP (Transmission Control Protocol) is a connection-oriented, reliable transport protocol, suitable for application scenarios requiring data integrity and sequence guarantees.
TCP Characteristics
- ✅ Connection-oriented: Requires connection establishment first
- ✅ Reliable transmission: Guarantees data arrival, order, and integrity
- ✅ Flow control: Prevents network congestion
- ✅ Congestion control: Automatically adjusts transmission rate
- ❌ Higher overhead: More protocol overhead compared to UDP
Applicable Scenarios
- File transfer
- Chat applications
- Remote control
- Database connections
- 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
' 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 interface
txtReceive.SelStart = Len(txtReceive.Text)
txtReceive.SelText = sData & vbCrLf
txtReceive.SelStart = Len(txtReceive.Text)
End Sub
' Connection close 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 through DataArrival
7. Cleanup when client disconnectsComplete Example
' 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 "Unable to 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 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 triggers 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 close 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 demo here
IsInBlacklist = False
End FunctionAdvanced Features
🔄 Heartbeat Detection
cWinsock's built-in heartbeat manager, embedded cTimer automatic drive, no manual implementation needed.
Server: Timeout Detection
' Configure heartbeat when starting server
m_oServer.AutoHeartbeat = True
m_oServer.HeartbeatTimeout = 120 ' 2 minutes no activity then timeout
' Timeout event
Private Sub m_oServer_ClientTimeout(Client As cWinsock)
Debug.Print "Client " & Client.Tag & " timeout, automatically disconnected"
UpdateClientList
End SubClient: Heartbeat Keepalive
' Enable heartbeat after connection
m_oClient.AutoHeartbeat = True
m_oClient.HeartbeatInterval = 50 ' 50 seconds no activity then send heartbeat
' Heartbeat event
Private Sub m_oClient_HeartbeatSent(Client As cWinsock)
Debug.Print "Heartbeat sent, idle: " & Client.IdleSeconds & " seconds"
End SubCustom Heartbeat Packet
' Default heartbeat packet is single byte &H00, can be customized
Dim baHB(0 To 3) As Byte
baHB(0) = &H50 ' P
baHB(1) = &H49 ' I
baHB(2) = &H4E ' N
baHB(3) = &H47 ' G
m_oClient.HeartbeatData = baHBWorking Principle:
- Heartbeat manager embedded
cTimer, triggers check every 10 seconds - Server: Checks all clients'
IdleSeconds, triggersClientTimeoutand auto-disconnects if timeout - Client: If idle exceeds
HeartbeatIntervalsends heartbeat packet, intelligently skips when data is sent/received - Each send/receive automatically resets
LastActivityTime
📦 Data Packet Protocol
cWinsock has three built-in packet protocols, automatically handles TCP fragmentation/sticky packet issues.
Delimiter Protocol (Suitable for text protocols)
m_oServer.PacketProtocol = ppDelimiter
m_oServer.Delimiter = vbCrLf ' Newline delimiter, suitable for line-based protocols
' Send automatically appends delimiter
Client.SendData "Hello" ' Actually sends: "Hello" + vbCrLf
' Receive automatic unpacket
Private Sub m_oServer_MessageArrival(Client As cWinsock, ByVal bytesTotal As Long)
Debug.Print "Complete message: " & Client.GetDataText()
End SubFixed Length Protocol (Suitable for fixed-length messages)
m_oServer.PacketProtocol = ppFixedLength
m_oServer.FixedLength = 256 ' Each message fixed 256 bytesLength Header Protocol (Suitable for binary protocols)
m_oServer.PacketProtocol = ppLengthHeader
m_oServer.HeaderBytes = 4 ' 4-byte length header
m_oServer.HeaderEndian = eeLittleEndian ' Little-endian
' Send automatically adds length header
Client.SendData "Hello" ' Actually sends: [4-byte length] + "Hello"
' Receive automatically strips length header
Private Sub m_oServer_MessageArrival(Client As cWinsock, ByVal bytesTotal As Long)
Dim baData() As Byte
baData = Client.GetDataByteArray()
ProcessBinaryMessage baData
End SubConfiguration Inheritance: New clients automatically inherit server's protocol and heartbeat configuration, each client holds independent instance, buffers don't interfere with each other.
🔄 Auto Reconnect
' 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
' Flow-controlled file transfer
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 complete
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 complete"
End Sub
Private Sub m_oClient_SendComplete(Client As cWinsock)
m_bSending = False
End SubFAQ
❓ Issue 1: Connection Refused
Symptom: Error 10061 - Connection refused
Causes:
- Server not started
- Port blocked by firewall
- Wrong IP address or port
Solution:
' Check if server is started
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
Causes:
- Network unreachable
- Server slow response
- Firewall blocking
Solution:
' 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 other party
Causes:
- Network issues
- Buffer overflow
- Other party not reading correctly
Solution:
' Confirm other party 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 "Other party confirmed receipt"
Else
Debug.Print "No acknowledgment received, resending"
m_oClient.SendData "DATA:" & sData
End If
End SubLast Updated: 2026-06-09