cWinsock Class Development Documentation
🚀 cWinsock - Simplified VB6 Winsock wrapper library, developed by woeoio@qq.com based on VbAsyncSocket (author: wqweto@gmail.com)
📖 Table of Contents
- Overview
- Core Highlights
- Comparison with Native Winsock Control
- Quick Start
- Architecture Design
- Documentation Index
Overview
cWinsock is a lightweight network communication class designed for VB6, providing an event-driven programming model similar to the classic Winsock control, but with a simpler API and more powerful features.
✨ Main Features
- 🔌 Pure class implementation - No controls required, direct object programming
- 🎯 Direct object reference - Event parameters directly pass client objects, no index lookup needed
- 🌐 Dual protocol support - Simultaneously supports TCP and UDP communication
- 🏢 Automatic client management - Server mode automatically manages all connected clients
- 📦 Smart data encoding - Supports multiple text encodings (GBK/ACP, UTF-8, Unicode)
- 🛡️ Connection interception - Blacklist/whitelist mechanism via
ConnectionRequestevent - 🔄 Event proxy mechanism - Server client data unified through server event triggering
- 💾 Flexible data types - Supports both string and byte array data formats
- 🚀 Planned features - Data packet protocol, TCP smart heartbeat, GetData enhanced methods
Core Highlights
1️⃣ Direct Object Reference Event Model 🔗
Traditional Winsock control problems:
' Need to manage clients via index
Private Sub Winsock1_ConnectionRequest(Index As Integer, ByVal requestID As Long)
Dim i As Integer
' Find available index or dynamically load control...
End Sub
' When processing data, need to know which client
Private Sub Winsock1_DataArrival(Index As Integer, ByVal bytesTotal As Long)
Winsock1(Index).GetData strData
End SubcWinsock's elegant solution:
' Event directly passes client object!
Private Sub m_oServer_ConnectionRequest(Client As cWinsock, ByRef DisConnect As Boolean)
' Directly operate on Client object, no index needed
Debug.Print "New client: " & Client.RemoteHostIP
' Reject blacklist IP
If IsBlacklisted(Client.RemoteHostIP) Then
DisConnect = True
End If
End Sub
' Data event also directly passes client object
Private Sub m_oServer_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)
Dim sData As String
Client.GetData sData
' Directly read data from Client object, no index lookup needed
End Sub2️⃣ Smart TCP Client Event Proxy 📡
Problem scenario: After server accepts new connection and creates client object, its data reception event cannot be subscribed by host.
cWinsock's solution: Automatically trigger events through parent server object
' In server object's DataArrival event
' Can receive data from all clients!
Private Sub m_oServer_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)
Dim sData As String
Client.GetData sData
' Client parameter is the specific client object
' Can directly reply to that client
Client.SendData "Echo: " & sData
End SubHow it works:
- Server accepts new connection, creates independent client socket object
- Client receives data, triggers event via parent server's
RaiseDataArrivalEventmethod - Host only needs to subscribe to server object events to handle all client data
3️⃣ UDP Server Virtual Client Management 🎭
UDP is a connectionless protocol, but cWinsock creates virtual client objects for each different remote address:port combination, simulating connection behavior:
' UDP server mode
Private Sub m_oUdp_ConnectionRequest(Client As cWinsock, ByRef DisConnect As Boolean)
' Each remote address:port combination that communicates for the first time
' Automatically creates a virtual Client object
Debug.Print "UDP client: " & Client.RemoteHostIP & ":" & Client.RemotePort
End Sub
Private Sub m_oUdp_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)
Dim sData As String
Client.GetData sData
' Can reply to specific virtual client
' cWinsock automatically uses correct target address:port
Client.SendData "Reply: " & sData
End Sub4️⃣ Connection Request Interception Mechanism 🚦
Implement connection interception via DisConnect parameter in ConnectionRequest event:
Private Sub m_oServer_ConnectionRequest(Client As cWinsock, ByRef DisConnect As Boolean)
' Blacklist check
If IsInBlacklist(Client.RemoteHostIP) Then
Debug.Print "Reject blacklist IP: " & Client.RemoteHostIP
DisConnect = True ' Set to True, automatically disconnect and cleanup resources
Exit Sub
End If
' Port range restriction
If Client.RemotePort < 1024 Then
Debug.Print "Reject privileged port connection: " & Client.RemotePort
DisConnect = True
Exit Sub
End If
' Whitelist mode
If m_bWhitelistMode And Not IsInWhitelist(Client.RemoteHostIP) Then
Debug.Print "Not in whitelist, reject connection"
DisConnect = True
Exit Sub
End If
' Keep DisConnect False, accept connection
Debug.Print "Accept connection: " & Client.RemoteHostIP & ":" & Client.RemotePort
End Sub5️⃣ Flexible Text Encoding Support 🔤
Supports multiple encoding methods to adapt to different scenarios:
' Default uses ACP/GBK encoding (compatible with VB6)
Client.SendData "中文测试"
Client.GetData sData ' Default ACP
' Use UTF-8 encoding (recommended for network transmission)
Client.SendData "中文测试", ucsScpUtf8
Client.GetData sData, , , ucsScpUtf8
' Use Unicode (no conversion, keep wide characters)
Client.SendData "中文测试", ScpUnicode
Client.GetData sData, , , ScpUnicode
' Send byte array (no encoding involved)
Dim baData() As Byte
baData = GetByteArray()
Client.SendData baDataEncoding enumeration:
ScpAcp(0) - System default code page (GBK on Chinese Windows)ScpUtf8(65001) - UTF-8 encodingScpUnicode(-1) - Unicode, no encoding conversion
6️⃣ Automatic Client Collection Management 📚
In server mode, automatically maintains all connected clients:
' Client collection automatically initialized when server starts
m_oServer.Listen 8080
' Iterate through all clients
Dim oClient As cWinsock
For Each oClient In m_oServer.Clients
Debug.Print "Client: " & oClient.Tag & " - " & oClient.RemoteHostIP
Next
' Get client count
Debug.Print "Current connections: " & m_oServer.ClientCount
' Manually remove client (usually automatically handled by CloseEvent)
m_oServer.RemoveClient oClient7️⃣ Smart Remote Address Resolution 🌐
UDP server mode supports domain name resolution:
' Set remote address (can be IP or domain name)
m_oUdp.RemoteHost = "example.com"
m_oUdp.RemotePort = 8888
' Domain name automatically resolved when sending
m_oUdp.SendData "Hello"Internal logic:
' Smart selection in SendData method
If LenB(m_sRemoteHostIP) <> 0 Then
' If resolved IP exists, prioritize using it
m_oSocket.SendText Data, m_sRemoteHostIP, m_lRemotePort, CodePage
ElseIf LenB(m_sRemoteHost) <> 0 Then
' Otherwise use hostname, underlying layer automatically resolves domain name
m_oSocket.SendText Data, m_sRemoteHost, m_lRemotePort, CodePage
End If8️⃣ Data Buffer Management 📊
Built-in data buffer, supports partial reading:
' When receiving data, only read first 100 bytes
Dim sPartial As String
Client.GetData sPartial, vbString, 100
' Remaining data automatically saved in internal buffer
' Will continue to return remaining data on next readInternal buffer mechanism:
- TCP and client mode: Use
m_baRecvBufferprivate member - UDP server virtual client: Use
UserDataproperty for temporary storage
9️⃣ Planned Feature Highlights (In Development) 🚀
Data Packet Protocol 📦
Problem scenario: TCP is a streaming protocol with data fragmentation and sticky packet issues
' Sender sends continuously
Client.SendData "Hello"
Client.SendData "World"
' Receiver may receive
"HelloWorld" ' Sticky packet
"Hel" ' Fragmentation
"loWorld"Planned implementation:
- Character delimiter protocol
- Default delimiter:
\0(VbNullChar) - Support custom arbitrary delimiters (such as
\r\n,|, etc.) - Applicable to text protocols
- Default delimiter:
- Fixed length protocol - Applicable to fixed-length messages
- Length header protocol - Applicable to binary protocols
- Custom protocol - Support user callback functions
- Unified protocol interface - All protocol classes provide unified
Encode(packet) andDecode(unpacket) functions, internally automatically cache fragmented data - Independent protocol instance per client - In multi-client scenarios, each client holds independent protocol instance, buffers isolated from each other
- Automatic processing - Automatically packet/unpacket after setting
Expected API:
' Set character delimiter protocol (use default \r\n)
Server.PacketProtocol = ppDelimiter
' Customize delimiter as null character
Server.Delimiter = vbNullChar
' Send automatic packet
Client.SendData "Hello World" ' Automatically append delimiter
' Receive automatic unpacket (handled by protocol class's internal Decode function)
Private Sub Server_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)
Dim sData As String
Client.GetData sData ' Automatically assemble complete message
End SubDetailed design: See Development Plan
TCP Smart Heartbeat 💓
Problem scenario: TCP connection may silently disconnect due to network issues, need keep-alive mechanism
Server features:
- Periodically poll client last communication time
- Automatically disconnect after 2 minutes of no communication
- Trigger
ClientTimeoutevent - Prevent zombie connections from occupying resources
- Important: Immediately reset client's
LastActivityTimeafter each send/receive to ensure heartbeat skipping cycle won't be misjudged as timeout
Client features:
- Automatically send heartbeat packet (1 byte) every 50 seconds
- Smart skip: Skip current cycle if recent data send/receive exists
- Keep connection active, prevent timeout disconnect
Expected API:
' Server configuration
Server.HeartbeatTimeout = 120 ' 2 minutes timeout
Server.AutoHeartbeat = True ' Auto enable
' Client configuration
Client.HeartbeatInterval = 50 ' 50 seconds interval
Client.HeartbeatData = &H0 ' Heartbeat packet content
Client.AutoHeartbeat = True
' Events
Private Sub Server_ClientTimeout(Client As cWinsock)
Debug.Print "Client timeout: " & Client.RemoteHostIP
End Sub
Private Sub Client_HeartbeatSent()
Debug.Print "Heartbeat sent"
End SubDetailed design: See Development Plan
GetData Enhanced Methods 🎯
Problem scenario: Getting data requires manual format conversion, code is tedious
Design principles:
- Unlike original
GetData, new methods output data via return value, not byref parameter - Support one-line code style:
Dim Data As String: Data = GetDataText()
Planned new methods:
' Directly return text
Debug.Print Client.GetDataText() ' One-line code
Debug.Print Client.GetDataTextUTF8() ' UTF-8 text
Debug.Print Client.GetDataTextUnicode() ' Unicode text
' Directly return hex
Debug.Print Client.GetDataHex() ' "48 65 6C 6C 6F"
' Directly return byte array
Dim baData() As Byte
baData = Client.GetDataByteArray()
' Condition check
If Client.GetDataText() = "Hello" Then
Debug.Print "Received Hello"
End If
' Function call processing
Dim sReply As String
sReply = ProcessData(Client.GetDataText())Detailed design: See Development Plan
Comparison with Native Winsock Control
| Feature | Native Winsock Control | cWinsock Class |
|---|---|---|
| Object model | Control array, managed via index | Pure class object, direct reference |
| Event parameters | Pass index, need reverse lookup object | Directly pass client object |
| Client management | Manually maintain index and controls | Automatically manage Clients collection |
| UDP server | Connectionless, no client concept | Virtual client objects |
| Connection interception | Need to manually close after Accept | Event parameter control, auto cleanup |
| Encoding support | Fixed encoding | Multiple encoding options |
| Data types | String/byte array | String/byte array + flexible conversion |
| Event unification | Independent event per client | Server triggers all client events uniformly |
| Resource management | Need to manually Unload controls | Auto cleanup and garbage collection |
Quick Start
TCP Client Example
Private WithEvents m_oClient As cWinsock
Private Sub Form_Load()
Set m_oClient = New cWinsock
m_oClient.Protocol = sckTCPProtocol
m_oClient.Connect "127.0.0.1", 8080
End Sub
Private Sub m_oClient_Connect(Client As cWinsock)
Debug.Print "Connected to server"
Client.SendData "Hello, Server!"
End Sub
Private Sub m_oClient_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)
Dim sData As String
Client.GetData sData
Debug.Print "Received data: " & sData
End Sub
Private Sub Form_Unload(Cancel As Integer)
m_oClient.Close_
End SubTCP Server Example
Private WithEvents m_oServer As cWinsock
Private Sub Form_Load()
Set m_oServer = New cWinsock
m_oServer.Protocol = sckTCPProtocol
m_oServer.Listen 8080
End Sub
Private Sub m_oServer_ConnectionRequest(Client As cWinsock, ByRef DisConnect As Boolean)
Debug.Print "New client connection: " & Client.RemoteHostIP
' DisConnect = False means accept connection
End Sub
Private Sub m_oServer_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)
Dim sData As String
Client.GetData sData
Debug.Print "Data from client " & Client.Tag & ": " & sData
' Echo
Client.SendData "Echo: " & sData
End Sub
Private Sub m_oServer_CloseEvent(Client As cWinsock)
Debug.Print "Client disconnected: " & Client.Tag
End Sub
Private Sub Form_Unload(Cancel As Integer)
m_oServer.Close_
End SubUDP Communication Example
Private WithEvents m_oUdp As cWinsock
Private Sub Form_Load()
Set m_oUdp = New cWinsock
m_oUdp.Protocol = sckUDPProtocol
m_oUdp.Bind 8888
End Sub
Private Sub cmdSend_Click()
m_oUdp.RemoteHost = "127.0.0.1"
m_oUdp.RemotePort = 9999
m_oUdp.SendData "Hello, UDP!"
End Sub
Private Sub m_oUdp_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)
Dim sData As String
Client.GetData sData
Debug.Print "Received UDP data (" & Client.RemoteHostIP & ":" & Client.RemotePort & "): " & sData
End SubArchitecture Design
Class Hierarchy
cWinsock (public class)
├── m_oSocket: cAsyncSocket (internal encapsulation)
├── m_cClients: Collection (client collection)
├── m_oParentServer: cWinsock (parent server reference, clients only)
└── Events: Connect, CloseEvent, ConnectionRequest, DataArrival, SendProgress, SendComplete, ErrorObject Relationship Diagram
Server object
├── Socket (listening socket)
├── Clients collection
│ ├── Client object 1 (cWinsock)
│ │ ├── Socket (independent connection)
│ │ └── ParentServer → Server object
│ ├── Client object 2 (cWinsock)
│ │ ├── Socket (independent connection)
│ │ └── ParentServer → Server object
│ └── ...
└── Event handler
└── All client data triggered through thisState Machine
sckClosed (0)
├─ Connect() → sckResolvingHost → sckHostResolved → sckConnecting → sckConnected (7)
├─ Listen() → sckListening (2)
└─ Bind() → sckOpen (1)
sckListening (2)
└─ OnAccept → Create client → sckConnected
sckConnected (7)
└─ OnClose → sckClosed
Error → sckError (9)Documentation Index
| Document | Description |
|---|---|
| Events Reference | Detailed explanation and usage examples for all events |
| Property Reference | Description, type, and purpose of all properties |
| Method Reference | Parameters, return values, and usage examples for all methods |
| Encoding Guide | Usage instructions and best practices for text encoding |
| TCP Programming | TCP client and server programming guide |
| UDP Programming | UDP communication programming guide |
| Best Practices | Solutions for common scenarios and performance optimization recommendations |
| Development Plan | Project development progress tracking and future feature planning |
License
Based on VbAsyncSocket (wqweto@gmail.com)
Author
cWinsock: woeoio@qq.com
VbAsyncSocket: wqweto@gmail.com
Last updated: 2026-01-09