State | WinsockState | Read-only | Current Socket state |\r\n| Protocol | WinsockProtocol | Read/Write | Protocol type (TCP/UDP) |\r\n| RecvBuffer | Byte() | Read/Write | Custom receive buffer |\r\n| LocalPort | Long | Read/Write | Local port |\r\n| RemoteHost | String | Read/Write | Remote hostname |\r\n| RemotePort | Long | Read/Write | Remote port |\r\n| RemoteHostIP | String | Read-only | Resolved remote IP address |\r\n| LocalHostName | String | Read-only | Local hostname |\r\n| LocalIP | String | Read-only | Local IP address |\r\n| Tag | String | Read/Write | User-defined tag (pure business identifier, no longer used internally) |\r\n| ClientId | Long | Read-only | Server-assigned unique connection identifier (auto-increment, no duplicates) |\r\n| UserData | Variant | Read/Write | User-defined data |\r\n| SocketHandle | Long | Read-only | Socket handle |\r\n| BytesReceived | Long | Read-only | Available data byte count |\r\n| IsServer | Boolean | Read-only | Whether in server mode |\r\n| IsAcceptedClient | Boolean | Read-only | Whether accepted by server |\r\n| ParentServer | cWinsock | Read-only | Parent server object (client only) |\r\n| Clients | Collection | Read-only | Collection of all connected clients (server only) |\r\n| ClientCount | Long | Read-only | Client connection count (server only) |\r\n| CurrentUser | Variant | Read/Write | Bound username (user binding feature) |\r\n| CurrentUserToken | String | Read/Write | User authentication token (user binding feature) |\r\n| CurrentUserInfo | cJson | Read/Write | User extended info (user binding feature) |\r\n| CountUsers | Long | Read-only | Current bound user count (user binding feature) |\r\n| CountGroups | Long | Read-only | Current group count (user binding feature) |\r\n| PacketHandler | cPacketProtocol | Read/Write | Packet protocol handler object (advanced configuration) |\r\n| PacketProtocol | PacketProtocolType | Read/Write | Packet protocol type (quick setup) |\r\n| Delimiter | String | Read/Write | Delimiter protocol delimiter (default vbCrLf) |\r\n| FixedLength | Long | Read/Write | Fixed-length protocol message length |\r\n| HeaderBytes | Long | Read/Write | Length-header protocol header bytes (2 or 4, default 4) |\r\n| HeaderEndian | EndianEnum | Read/Write | Length-header protocol byte order (default little-endian) |\r\n| MaxPacketSize | Long | Read/Write | Single packet max bytes (default 1MB), prevent malicious oversized packets |\r\n| MaxBufferSize | Long | Read/Write | Buffer accumulation limit (default 4MB), prevent memory exhaustion |\r\n| Heartbeat | cHeartbeat | Read-only | Heartbeat manager object (advanced configuration) |\r\n| AutoHeartbeat | Boolean | Read/Write | Enable/disable auto heartbeat (embedded cTimer) |\r\n| HeartbeatTimeout | Long | Read/Write | Server heartbeat timeout seconds (default 120) |\r\n| HeartbeatInterval | Long | Read/Write | Client heartbeat interval seconds (default 50) |\r\n| HeartbeatData | Byte() | Read/Write | Heartbeat packet content (default single byte 0) |\r\n| IdleSeconds | Long | Read-only | Current idle seconds |\r\n\r\n---\r\n\r\n## 🔄 State Property\r\n\r\n### Description\r\n\r\nReturns the current Socket state.\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get State() As WinsockState\r\n\r\n\r\n### Return Values\r\n\r\n| Constant | Value | Description |\r\n|----------|-------|-------------|\r\n| sckClosed | 0 | Closed |\r\n| sckOpen | 1 | Open (after UDP binding) |\r\n| sckListening | 2 | Listening (TCP server) |\r\n| sckConnectionPending | 3 | Connection pending |\r\n| sckResolvingHost | 4 | Resolving hostname |\r\n| sckHostResolved | 5 | Hostname resolved |\r\n| sckConnecting | 6 | Connecting |\r\n| sckConnected | 7 | Connected |\r\n| sckClosing | 8 | Closing |\r\n| sckError | 9 | Error occurred |\r\n\r\n### Usage Example\r\n\r\nvb\r\nPrivate Sub cmdConnect_Click()\r\n If m_oClient.State = sckClosed Then\r\n m_oClient.Connect "127.0.0.1", 8080\r\n Else\r\n MsgBox "Socket not closed, current state: " & GetStateName(m_oClient.State)\r\n End If\r\nEnd Sub\r\n\r\nPrivate Function GetStateName(ByVal eState As WinsockState) As String\r\n Select Case eState\r\n Case sckClosed: GetStateName = "Closed"\r\n Case sckOpen: GetStateName = "Open"\r\n Case sckListening: GetStateName = "Listening"\r\n Case sckConnected: GetStateName = "Connected"\r\n Case sckClosing: GetStateName = "Closing"\r\n Case sckError: GetStateName = "Error"\r\n Case Else: GetStateName = "Unknown"\r\n End Select\r\nEnd Function\r\n\r\n\r\n---\r\n\r\n## 🌐 Protocol Property\r\n\r\n### Description\r\n\r\nGets or sets the protocol type used by the Socket.\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get Protocol() As WinsockProtocol\r\nProperty Let Protocol(ByVal Value As WinsockProtocol)\r\n\r\n\r\n### Values\r\n\r\n| Constant | Value | Description |\r\n|----------|-------|-------------|\r\n| sckTCPProtocol | 1 | TCP protocol (reliable, connection-oriented) |\r\n| sckUDPProtocol | 2 | UDP protocol (unreliable, connectionless) |\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Set to TCP protocol\r\nm_oSocket.Protocol = sckTCPProtocol\r\n\r\n' Set to UDP protocol\r\nm_oSocket.Protocol = sckUDPProtocol\r\n\r\n' Check current protocol\r\nIf m_oSocket.Protocol = sckTCPProtocol Then\r\n Debug.Print "Using TCP protocol"\r\nElse\r\n Debug.Print "Using UDP protocol"\r\nEnd If\r\n\r\n\r\n### ⚠️ Notes\r\n\r\n- Can only be modified when State = sckClosed\r\n- After modification, need to call Connect(), Listen() or Bind() again\r\n\r\n---\r\n\r\n## 📦 RecvBuffer Property\r\n\r\n### Description\r\n\r\nSets or gets custom receive buffer. Usually used for advanced scenarios.\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Let RecvBuffer(ByRef Value() As Byte)\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Set custom buffer\r\nDim baCustomBuffer() As Byte\r\nReDim baCustomBuffer(0 To 8191) ' 8KB buffer\r\nm_oSocket.RecvBuffer = baCustomBuffer\r\n\r\n\r\n---\r\n\r\n## 🔌 LocalPort Property\r\n\r\n### Description\r\n\r\nGets or sets local port number.\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get LocalPort() As Long\r\nProperty Let LocalPort(ByVal Value As Long)\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Set local port (must be done before calling Connect/Listen/Bind)\r\nm_oServer.LocalPort = 8080\r\nm_oServer.Listen\r\n\r\n' Get actual bound port\r\nDebug.Print "Local port: " & m_oSocket.LocalPort\r\n\r\n\r\n### ⚠️ Notes\r\n\r\n- Can only be set when State = sckClosed\r\n- Range: 0-65535\r\n- 0 means auto-assigned by system\r\n\r\n---\r\n\r\n## 🌍 RemoteHost Property\r\n\r\n### Description\r\n\r\nGets or sets remote hostname (domain name or IP).\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get RemoteHost() As String\r\nProperty Let RemoteHost(ByVal Value As String)\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Set remote host (can use domain name)\r\nm_oClient.RemoteHost = "example.com"\r\nm_oClient.RemotePort = 80\r\nm_oClient.Connect\r\n\r\n' Use IP address\r\nm_oClient.RemoteHost = "192.168.1.100"\r\nm_oClient.RemotePort = 8080\r\nm_oClient.Connect\r\n\r\n' Get remote hostname\r\nDebug.Print "Remote host: " & m_oClient.RemoteHost\r\n\r\n\r\n---\r\n\r\n## 🔢 RemotePort Property\r\n\r\n### Description\r\n\r\nGets or sets remote port number.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get RemotePort() As Long\r\nProperty Let RemotePort(ByVal Value As Long)\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Set remote port\r\nm_oClient.RemotePort = 8080\r\n\r\n' Get remote port\r\nDebug.Print "Remote port: " & m_oClient.RemotePort\r\n\r\n\r\n---\r\n\r\n## 🖥️ RemoteHostIP Property\r\n\r\n### Description\r\n\r\nGets resolved remote IP address (read-only).\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get RemoteHostIP() As String\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\nPrivate Sub m_oClient_Connect(Client As cWinsock)\r\n Debug.Print "Connection successful!"\r\n Debug.Print "Hostname: " & Client.RemoteHost\r\n Debug.Print "IP address: " & Client.RemoteHostIP\r\n Debug.Print "Port: " & Client.RemotePort\r\nEnd Sub\r\n\r\n\r\n### Special Case: UDP Server Virtual Client\r\n\r\nvb\r\nPrivate Sub m_oUdp_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)\r\n ' In UDP server mode, virtual client's RemoteHostIP returns sender IP\r\n Debug.Print "Received from " & Client.RemoteHostIP & ":" & Client.RemotePort\r\nEnd Sub\r\n\r\n\r\n---\r\n\r\n## 💻 LocalHostName Property\r\n\r\n### Description\r\n\r\nGets local hostname.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get LocalHostName() As String\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\nDebug.Print "Local hostname: " & m_oSocket.LocalHostName\r\n\r\n\r\n---\r\n\r\n## 🌐 LocalIP Property\r\n\r\n### Description\r\n\r\nGets local IP address.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get LocalIP() As String\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\nDebug.Print "Local IP: " & m_oSocket.LocalIP\r\n\r\n\r\n---\r\n\r\n## 🏷️ Tag Property\r\n\r\n### Description\r\n\r\nUser-defined tag for business identification or grouping. Can be freely read/written, internal management no longer relies on this property.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get Tag() As String\r\nProperty Let Tag(ByVal Value As String)\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Set business tag for client in ConnectionRequest\r\nPrivate Sub m_oServer_ConnectionRequest(Client As cWinsock, ByRef DisConnect As Boolean)\r\n Client.Tag = "Client-" & Client.RemoteHostIP\r\n Debug.Print "New client Tag: " & Client.Tag\r\nEnd Sub\r\n\r\n' Find client by Tag (need to iterate manually)\r\nPrivate Function FindClientByTag(ByVal sTag As String) As cWinsock\r\n Dim oClient As cWinsock\r\n For Each oClient In m_oServer.Clients\r\n If oClient.Tag = sTag Then\r\n Set FindClientByTag = oClient\r\n Exit Function\r\n End If\r\n Next\r\n Set FindClientByTag = Nothing\r\nEnd Function\r\n\r\n\r\n---\r\n\r\n## 🆔 ClientId Property\r\n\r\n### Description\r\n\r\nServer-assigned unique connection identifier (read-only). Auto-increment number, starting from 1, not reused after disconnect, never duplicates.\r\n\r\n- Server's own (Listen socket) ClientId = 0.\r\n- Both TCP and UDP client connections are auto-assigned.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get ClientId() As Long\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Identify client in ConnectionRequest or DataArrival\r\nPrivate Sub m_oServer_ConnectionRequest(Client As cWinsock, ByRef DisConnect As Boolean)\r\n Debug.Print "New client connected, ID: " & Client.ClientId & " from " & Client.RemoteHostIP\r\nEnd Sub\r\n\r\n' Use ID for logging or key mapping\r\nPrivate Sub m_oServer_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)\r\n Debug.Print "Client #" & Client.ClientId & " sent " & bytesTotal & " bytes"\r\nEnd Sub\r\n\r\n\r\n| Feature | Description |\r\n|---------|-------------|\r\n| Readability | #1, #42 instantly recognizable |\r\n| Uniqueness | Monotonically increasing, no duplicates within lifecycle |\r\n| Type | Long, easy to compare and store |\r\n\r\n---\r\n\r\n## 💾 UserData Property\r\n\r\n### Description\r\n\r\nUser-defined data storage, can store any type of data.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get UserData() As Variant\r\nProperty Let UserData(ByVal Value As Variant)\r\nProperty Set UserData(ByVal Value As Variant)\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Store string\r\nm_oClient.UserData = "User info: Zhang San"\r\n\r\n' Store number\r\nm_oClient.UserData = 12345\r\n\r\n' Store object\r\nDim oUserInfo As New CUserInfo\r\noUserInfo.Name = "Zhang San"\r\noUserInfo.Age = 25\r\nSet m_oClient.UserData = oUserInfo\r\n\r\n' Read data\r\nDim sInfo As String\r\nsInfo = m_oClient.UserData\r\nDebug.Print sInfo\r\n\r\n' Read object\r\nDim oUserData As CUserInfo\r\nSet oUserData = m_oClient.UserData\r\nDebug.Print oUserInfo.Name & ", " & oUserData.Age\r\n\r\n\r\n### Advanced Usage: Client Session Data\r\n\r\nvb\r\nPrivate Type tSessionData\r\n LoginTime As Date\r\n LastActivity As Date\r\n LoginAttempts As Long\r\n Authenticated As Boolean\r\nEnd Type\r\n\r\nPrivate Sub m_oServer_ConnectionRequest(Client As cWinsock, ByRef DisConnect As Boolean)\r\n Dim tSession As tSessionData\r\n tSession.LoginTime = Now\r\n tSession.LastActivity = Now\r\n tSession.LoginAttempts = 0\r\n tSession.Authenticated = False\r\n \r\n Client.UserData = tSession\r\nEnd Sub\r\n\r\nPrivate Sub CheckSessionTimeout()\r\n Dim oClient As cWinsock\r\n Dim tSession As tSessionData\r\n \r\n For Each oClient In m_oServer.Clients\r\n tSession = oClient.UserData\r\n If DateDiff("s", tSession.LastActivity, Now) > 300 Then ' 5 minutes of inactivity\r\n Debug.Print "Session timeout, disconnecting: " & oClient.ClientId\r\n oClient.Close_\r\n End If\r\n Next\r\nEnd Sub\r\n\r\n\r\n---\r\n\r\n## 🔑 SocketHandle Property\r\n\r\n### Description\r\n\r\nGets underlying Socket handle (read-only).\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get SocketHandle() As Long\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Get Socket handle\r\nDebug.Print "Socket handle: " & m_oSocket.SocketHandle\r\n\r\n' Used for advanced operations (e.g., Win32 API interaction)\r<arg_value>\r\nIf m_oSocket.SocketHandle <> 0 Then\r\n Call SomeWin32Function(m_oSocket.SocketHandle)\r\nEnd If\r\n\r\n\r\n---\r\n\r\n## 📊 BytesReceived Property\r\n\r\n### Description\r\n\r\nGets available byte count in receive buffer (read-only).\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get BytesReceived() As Long\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\nPrivate Sub m_oClient_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)\r\n Debug.Print "Event notification: " & bytesTotal & " bytes"\r\n Debug.Print "Buffer total: " & Client.BytesReceived & " bytes"\r\n \r\n ' Read only partial data\r\n If Client.BytesReceived > 100 Then\r\n Dim sData As String\r\n Client.GetData sData, vbString, 100 ' Read only first 100 bytes\r\n Debug.Print "Read partial data: " & sData\r\n End If\r\nEnd Sub\r\n\r\n\r\n---\r\n\r\n## 🏢 IsServer Property\r\n\r\n### Description\r\n\r\nDetermines if current object is in server mode (read-only).\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get IsServer() As Boolean\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\nPrivate Sub m_oServer_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)\r\n If Client.IsServer Then\r\n Debug.Print "Data from server"\r\n Else\r\n Debug.Print "Data from client"\r\n End If\r\nEnd Sub\r\n\r\n\r\n---\r\n\r\n## 🔗 IsAcceptedClient Property\r\n\r\n### Description\r\n\r\nDetermines if current object is a client accepted by server (read-only).\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get IsAcceptedClient() As Boolean\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\nPrivate Sub SomeFunction(oSocket As cWinsock)\r\n If oSocket.IsAcceptedClient Then\r\n Debug.Print "This is a client accepted by server"\r\n Debug.Print "Parent server: " & oSocket.ParentServer.Tag\r\n Else\r\n Debug.Print "This is an independent client or server object"\r\n End If\r\nEnd Sub\r\n\r\n\r\n---\r\n\r\n## 👆 ParentServer Property\r\n\r\n### Description\r\n\r\nGets parent server object (only valid for server-accepted clients).\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get ParentServer() As cWinsock\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\nPrivate Sub m_oServer_ConnectionRequest(Client As cWinsock, ByRef DisConnect As Boolean)\r\n ' Server sets ParentServer\r\n ' Client can access parent server\r\n \r\n Debug.Print "New client's parent server: " & Client.ParentServer.Tag\r\nEnd Sub\r\n\r\n\r\n### Advanced Usage: Client Broadcast Message\r\n\r\nvb\r\n' In some client event, broadcast to other clients through parent server\r\nPrivate Sub ClientBroadcastToOthers(ByVal oSender As cWinsock, ByVal sMessage As String)\r\n Dim oClient As cWinsock\r\n For Each oClient In oSender.ParentServer.Clients\r\n If Not oClient Is oSender Then ' Don't send to self\r\n oClient.SendData sMessage\r\n End If\r\n Next\r\nEnd Sub\r\n\r\n\r\n---\r\n\r\n## 👥 Clients Property\r\n\r\n### Description\r\n\r\nGets collection of all connected clients (only valid for server objects).\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get Clients() As Collection\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Iterate through all clients\r\nPrivate Sub ListAllClients()\r\n Debug.Print "Current connections: " & m_oServer.ClientCount\r\n \r\n Dim oClient As cWinsock\r\n For Each oClient In m_oServer.Clients\r\n Debug.Print oClient.Tag & ": " & oClient.RemoteHostIP & ":" & oClient.RemotePort\r\n Next\r\nEnd Sub\r\n\r\n' Find specific client\r\nPrivate Function FindClientByIP(ByVal sIP As String) As cWinsock\r\n Dim oClient As cWinsock\r\n For Each oClient In m_oServer.Clients\r\n If oClient.RemoteHostIP = sIP Then\r\n Set FindClientByIP = oClient\r\n Exit Function\r\n End If\r\n Next\r\n Set FindClientByIP = Nothing\r\nEnd Function\r\n\r\n' Broadcast to all clients\r\nPrivate Sub BroadcastToAll(ByVal sMessage As String)\r\n Dim oClient As cWinsock\r\n For Each oClient In m_oServer.Clients\r\n On Error Resume Next\r\n oClient.SendData sMessage\r\n On Error GoTo 0\r\n Next\r\nEnd Sub\r\n\r\n\r\n---\r\n\r\n## 🔢 ClientCount Property\r\n\r\n### Description\r\n\r\nGets current number of connected clients (read-only, only valid for server objects).\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get ClientCount() As Long\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Display connection count\r\nlblClientCount.Caption = "Current connections: " & m_oServer.ClientCount\r\n\r\n' Limit maximum connections\r\nPrivate Sub m_oServer_ConnectionRequest(Client As cWinsock, ByRef DisConnect As Boolean)\r\n If m_oServer.ClientCount >= m_lMaxClients Then\r\n Debug.Print "Maximum connection limit reached: " & m_lMaxClients\r\n DisConnect = True\r\n End If\r\nEnd Sub\r\n\r\n\r\n---\r\n\r\n## 👤 CurrentUser Property\r\n\r\n### Description\r\n\r\nGets or sets bound username (for user binding feature). After binding user with BindUser method, this property is automatically set to the username.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nPublic CurrentUser As Variant\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Bind user when client connects\r\nPrivate Sub m_oServer_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)\r\n Dim sData As String\r\n Client.GetData sData\r\n \r\n If Left$(sData, 6) = "LOGIN:" Then\r\n Dim sUsername As String\r\n sUsername = Mid$(sData, 7)\r\n \r\n ' Bind user\r\n m_oServer.BindUser sUsername, Client\r\n \r\n ' Verify binding successful\r\n Debug.Print "Client.CurrentUser = " & Client.CurrentUser\r\n End If\r\nEnd Sub\r\n\r\n' Check if user is logged in\r\nPrivate Sub CheckUserLogin(ByVal oClient As cWinsock)\r\n If LenB(CStr(oClient.CurrentUser)) = 0 Then\r\n Debug.Print "User not logged in"\r\n Else\r\n Debug.Print "Current user: " & oClient.CurrentUser\r\n End If\r\nEnd Sub\r\n\r\n\r\n### Difference from Tag Property\r\n\r\n| Property | Purpose | Setting Method |\r\n|----------|---------|----------------|\r\n| Tag | User-defined business identifier | Manually set |\r\n| ClientId | System-assigned connection number | Auto-assigned by server |\r\n| CurrentUser | Identifies logged-in user | Bound via BindUser |\r\n\r\n### Auto Cleanup\r\n\r\nWhen client disconnects (calls Close_ or object is destroyed), system automatically unbinds user, no manual handling needed.\r\n\r\n---\r\n\r\n## 🔑 CurrentUserToken Property\r\n\r\n### Description\r\n\r\nGets or sets user authentication token (for user binding feature). When binding user with BindUser method and passing Token parameter, this property is automatically set to the corresponding value.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nPublic CurrentUserToken As String\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Bind user with Token\r\nm_oServer.BindUser "alice", Client, "jwt_token_xyz123"\r\n\r\n' Verify Token later\r\nIf Client.CurrentUserToken = "jwt_token_xyz123" Then\r\n Debug.Print "Token verification passed"\r\nEnd If\r\n\r\n' Get current user's Token\r\nDebug.Print "User " & Client.CurrentUser & "'s Token: " & Client.CurrentUserToken\r\n\r\n\r\n---\r\n\r\n## 📋 CurrentUserInfo Property\r\n\r\n### Description\r\n\r\nGets or sets user extended info (for user binding feature). When binding user with BindUser method and passing Info parameter (cJson object), this property is automatically set to the corresponding value. Can be used to store additional user metadata such as login time, IP address, permission level, etc.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nPublic CurrentUserInfo As cJson\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Bind user with extended info\r\nDim oInfo As New cJson\r\noInfo.Add "loginTime", Now\r\noInfo.Add "ip", Client.RemoteHostIP\r\noInfo.Add "role", "admin"\r\nm_oServer.BindUser "alice", Client, , oInfo\r\n\r\n' Read user extended info\r\nDebug.Print "Login time: " & Client.CurrentUserInfo.Item("loginTime")\r\nDebug.Print "Role: " & Client.CurrentUserInfo.Item("role")\r\n\r\n' Dynamically add info\r\nClient.CurrentUserInfo.Add "lastActivity", Now\r\n\r\n\r\n### Difference from UserData\r\n\r\n| Property | Purpose | Lifecycle |\r\n|----------|---------|-----------|\r\n| UserData | General custom data storage | Manually managed by user |\r\n| CurrentUserInfo | User-bound structured info (JSON) | Auto-managed with BindUser/UnbindUser |\r\n\r\n---\r\n\r\n## 🔢 CountUsers Property\r\n\r\n### Description\r\n\r\nGets current number of bound users (read-only). Users bound via BindUser method are counted.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get CountUsers() As Long\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Display current bound user count\r\nDebug.Print "Current bound users: " & m_oServer.CountUsers\r\n\r\n' Monitor user login status\r\nPrivate Sub UpdateUserCount()\r\n lblUserCount.Caption = "Online users: " & m_oServer.CountUsers\r\nEnd Sub\r\n\r\n' Check in DataArrival\r\nPrivate Sub m_oServer_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)\r\n Debug.Print "Current total bound users: " & m_oServer.CountUsers\r\nEnd Sub\r\n\r\n\r\n---\r\n\r\n## 👥 CountGroups Property\r\n\r\n### Description\r\n\r\nGets current number of groups (read-only). Groups created via AddGroup method are counted.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get CountGroups() As Long\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Display current group count\r\nDebug.Print "Current group count: " & m_oServer.CountGroups\r\n\r\n' Create default groups on initialization\r\nPrivate Sub InitializeGroups()\r\n If m_oServer.CountGroups = 0 Then\r\n m_oServer.AddGroup "Default"\r\n m_oServer.AddGroup "Admins"\r\n End If\r\nEnd Sub\r\n\r\n\r\n---\r\n\r\n## 📦 PacketHandler Property\r\n\r\n### Description\r\n\r\nGets or sets packet protocol handler object. Each cWinsock instance holds independent protocol instance, multi-client互不干扰.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get PacketHandler() As cPacketProtocol\r\nProperty Set PacketHandler(ByVal Value As cPacketProtocol)\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Advanced configuration: directly operate protocol object\r\nDim oProtocol As cPacketProtocol\r\nSet oProtocol = New cPacketProtocol\r\noProtocol.ProtocolType = ppLengthHeader\r\noProtocol.HeaderBytes = 4\r<arg_value>\r\noProtocol.Endian = eeBigEndian\r\n\r\nSet m_oServer.PacketHandler = oProtocol\r\n\r\n\r\n---\r\n\r\n## 📦 PacketProtocol Property\r\n\r\n### Description\r\n\r\nQuick setup for packet protocol type. Setting automatically creates protocol handler (if not existing). Set to ppNone to disable protocol.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get PacketProtocol() As PacketProtocolType\r<arg_value>\r\nProperty Let PacketProtocol(ByVal Value As PacketProtocolType)\r\n\r\n\r\n### Values\r\n\r\n| Constant | Value | Description |\r\n|----------|-------|-------------|\r\n| ppNone | 0 | No protocol (default) |\r\n| ppDelimiter | 1 | Character delimiter protocol |\r\n| ppFixedLength | 2 | Fixed-length protocol |\r\n| ppLengthHeader | 3 | Length-header protocol |\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Set delimiter protocol\r\nm_oServer.PacketProtocol = ppDelimiter\r\nm_oServer.Delimiter = vbCrLf\r\n\r\n' Set length-header protocol\r\nm_oServer.PacketProtocol = ppLengthHeader\r\nm_oServer.HeaderBytes = 4\r\n\r\n' Disable protocol\r\nm_oServer.PacketProtocol = ppNone\r\n\r\n\r\n---\r\n\r\n## 📦 Delimiter Property\r\n\r\n### Description\r\n\r\nSets or gets delimiter protocol delimiter. Default is vbCrLf. Only effective when PacketProtocol = ppDelimiter.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get Delimiter() As String\r<arg_value>\r\nProperty Let Delimiter(ByVal Value As String)\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Use newline as delimiter (suitable for text line protocol)\r\nm_oServer.PacketProtocol = ppDelimiter\r\nm_oServer.Delimiter = vbCrLf\r\n\r\n' Use null character as delimiter (suitable for binary-text mixed protocol)\r\nm_oServer.Delimiter = vbNullChar\r\n\r\n' Use custom delimiter\r<arg_value>\r\nm_oServer.Delimiter = "<EOF>"\r\n\r\n\r\n---\r\n\r\n## 📦 FixedLength Property\r\n\r\n### Description\r\n\r\nSets or gets fixed-length protocol message length. Only effective when PacketProtocol = ppFixedLength.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get FixedLength() As Long\r\nProperty Let FixedLength(ByVal Value As Long)\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Each message fixed 256 bytes\r\nm_oServer.PacketProtocol = ppFixedLength\r\nm_oServer.FixedLength = 256\r\n\r\n\r\n---\r\n\r\n## 📦 HeaderBytes Property\r\n\r\n### Description\r\n\r\nSets or gets length-header protocol header bytes. 2 means Integer (max 65535 bytes), 4 means Long. Default is 4. Only effective when PacketProtocol = ppLengthHeader.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get HeaderBytes() As Long\r\nProperty Let HeaderBytes(ByVal Value As Long)\r\n\r\n\r\n### Values\r\n\r\n| Value | Description | Max Message Length |\r\n|-------|-------------|-------------------|\r\n| 2 | 2-byte header (Unsigned Integer) | 65,535 bytes |\r\n| 4 | 4-byte header (Unsigned Long) | 2,147,483,647 bytes |\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Small messages use 2-byte header to save bandwidth\r\nm_oServer.PacketProtocol = ppLengthHeader\r\nm_oServer.HeaderBytes = 2\r\n\r\n' Large messages use 4-byte header\r\nm_oServer.HeaderBytes = 4\r\n\r\n\r\n---\r\n\r\n## 📦 HeaderEndian Property\r\n\r\n### Description\r\n\r\nSets or gets length-header protocol byte order. Default is little-endian (eeLittleEndian). Only effective when PacketProtocol = ppLengthHeader.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r<arg_value>\r\nProperty Get HeaderEndian() As EndianEnum\r\nProperty Let HeaderEndian(ByVal Value As EndianEnum)\r\n\r\n\r\n### Values\r\n\r\n| Constant | Value | Description |\r\n|----------|-------|-------------|\r\n| eeLittleEndian | 0 | Little-endian (default, x86/x64) |\r\n| eeBigEndian | 1 | Big-endian (network byte order) |\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Communicate with Java/network protocols (usually use big-endian)\r\nm_oServer.PacketProtocol = ppLengthHeader\r\nm_oServer.HeaderEndian = eeBigEndian\r\n\r\n\r\n---\r\n\r\n## 📦 MaxPacketSize Property\r\n\r\n### Description\r\n\r\nSingle packet max byte limit. During length-header protocol parsing, if declared message length exceeds this value, error is thrown and packet discarded. Prevents malicious oversized packet declarations exhausting memory.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get MaxPacketSize() As Long\r\nProperty Let MaxPacketSize(ByVal Value As Long)\r\n\r\n\r\n### Default Value\r\n\r\n1MB (1048576 bytes)\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Adjust max packet limit\r\nm_oServer.PacketProtocol = ppLengthHeader\r<arg_value>\r\nm_oServer.MaxPacketSize = 524288 ' 512KB\r\n\r\n' New clients automatically inherit this configuration\r\n\r\n\r\n### Notes\r\n\r\n- Only effective for ppLengthHeader protocol\r\n- Throws clear error message when exceeded\r\n- New clients automatically inherit server configuration\r\n\r\n---\r\n\r\n## 📦 MaxBufferSize Property\r\n\r\n### Description\r\n\r\nReceive buffer accumulation limit. Decode checks before merging buffer, if exceeded, error is thrown and packet discarded. Prevents large amounts of incomplete packets slowly consuming memory (e.g., attacker sending many incomplete packets).\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get MaxBufferSize() As Long\r\nProperty Let MaxBufferSize(ByVal Value As Long)\r\n\r\n\r\n### Default Value\r\n\r\n4MB (4194304 bytes)\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Adjust buffer limit\r\nm_oServer.PacketProtocol = ppLengthHeader\r\nm_oServer.MaxBufferSize = 8388608 ' 8MB\r\n\r\n\r\n### Notes\r\n\r\n- Effective for all protocol types\r\n- Throws clear error message when exceeded\r\n- New clients automatically inherit server configuration\r\n\r\n---\r\n\r\n## 💓 Heartbeat Property\r\n\r\n### Description\r\n\r<arg_value>\r\nGets heartbeat manager object for advanced configuration. Heartbeat manager embeds cTimer auto-drive, no external timer needed.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get Heartbeat() As cHeartbeat\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Advanced configuration\r\nIf Not m_oServer.Heartbeat Is Nothing Then\r\n Debug.Print "Heartbeat sent count: " & m_oServer.Heartbeat.HeartbeatCount\r\n Debug.Print "Timer interval: " & m_oServer.Heartbeat.TimerInterval & "ms"\r\nEnd If\r\n\r\n\r\n---\r\n\r\n## 💓 AutoHeartbeat Property\r\n\r\n### Description\r\n\r\nEnable or disable auto heartbeat. When enabled, embedded cTimer auto-drive, no external timer or PollHeartbeat() call needed.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get AutoHeartbeat() As Boolean\r\nProperty Let AutoHeartbeat(ByVal Value As Boolean)\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Server: Enable heartbeat detection\r\nm_oServer.AutoHeartbeat = True\r\nm_oServer.HeartbeatTimeout = 120 ' 2 minutes timeout\r\n\r\n' Client: Enable heartbeat keep-alive\r\nm_oClient.AutoHeartbeat = True\r<arg_value>\r\nm_oClient.HeartbeatInterval = 50 ' 50 seconds interval\r\n\r\n' Disable heartbeat\r\nm_oServer.AutoHeartbeat = False\r\n\r\n\r\n---\r\n\r\n## 💓 HeartbeatTimeout Property\r\n\r\n### Description\r\n\r\nServer heartbeat timeout seconds. Client idle time exceeding this value will be auto-disconnected. Default 120 seconds (2 minutes). Only effective in server mode with AutoHeartbeat = True.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r<arg_value>\r\nProperty Get HeartbeatTimeout() As Long\r\nProperty Let HeartbeatTimeout(ByVal Value As Long)\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\nm_oServer.AutoHeartbeat = True\r<arg_value>\r\nm_oServer.HeartbeatTimeout = 180 ' 3 minutes timeout\r\n\r\n\r\n---\r\n\r\n## 💓 HeartbeatInterval Property\r\n\r\n### Description\r\n\r\nClient heartbeat interval seconds. When idle time exceeds this value, client auto-sends heartbeat packet. Default 50 seconds. Only effective in client mode with AutoHeartbeat = True.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get HeartbeatInterval() As Long\r\nProperty Let HeartbeatInterval(ByVal Value As Long)\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\nm_oClient.AutoHeartbeat = True\r\nm_oClient.HeartbeatInterval = 30 ' 30 seconds no activity then send heartbeat\r\n\r\n\r\n---\r\n\r\n## 💓 HeartbeatData Property\r\n\r\n### Description\r\n\r\nHeartbeat packet content (byte array). Default is single byte &H00. Can customize heartbeat packet format based on protocol.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get HeartbeatData() As Byte()\r\nProperty Let HeartbeatData(ByRef Value() As Byte)\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Custom heartbeat packet content\r\nDim baHB(0 To 3) As Byte\r\nbaHB(0) = &HFF\r\nbaHB(1) = &H0\r\nbaHB(2) = &H0\r\nbaHB(3) = &HFF\r\nm_oClient.HeartbeatData = baHB\r\n\r\n\r\n---\r\n\r\n## 💓 IdleSeconds Property\r\n\r\n### Description\r\n\r\nCurrent connection idle seconds (read-only). Calculated from last send/receive time. Can be used to determine connection activity level.\r\n\r\n\r\n\r\n### Syntax\r\n\r\nvb\r\nProperty Get IdleSeconds() As Long\r\n\r\n\r\n### Usage Example\r\n\r\nvb\r\n' Check client activity level\r\nDim oClient As cWinsock\r<arg_value>\r\nFor Each oClient In m_oServer.Clients\r\n Debug.Print "Client #" & oClient.ClientId & " idle: " & oClient.IdleSeconds & " seconds"\r\nNext\r\n\r\n\r\n---\r\n\r\n## 📌 Property Usage Scenarios Summary\r\n\r\n### Common Client Properties\r\n\r\nvb\r\n' Set before connecting\r\nm_oClient.Protocol = sckTCPProtocol\r\nm_oClient.RemoteHost = "192.168.1.100"\r\nm_oClient.RemotePort = 8080\r\nm_oClient.Connect\r\n\r\n' Get after connecting\r\nDebug.Print "IP: " & m_oClient.RemoteHostIP\r\nDebug.Print "Port: " & m_oClient.RemotePort\r<arg_value>\r\nDebug.Print "State: " & m_oClient.State\r\n\r\n' Custom tags\r\nm_oClient.Tag = "Client-001"\r<arg_value>\r\nm_oClient.UserData = "User info"\r\n\r\n\r\n### Common Server Properties\r\n\r\nvb\r\n' Start server\r\nm_oServer.Protocol = sckTCPProtocol\r\nm_oServer.LocalPort = 8080\r\nm_oServer.Listen\r\n\r\n' Set packet protocol\r\nm_oServer.PacketProtocol = ppDelimiter\r\nm_oServer.Delimiter = vbCrLf\r\n\r\n' Set heartbeat\r\nm_oServer.AutoHeartbeat = True\r\nm_oServer.HeartbeatTimeout = 120\r\n\r\n' Manage clients\r\nDebug.Print "Connections: " & m_oServer.ClientCount\r\n\r\nDim oClient As cWinsock\r<arg_value>\r\nFor Each oClient In m_oServer.Clients\r<arg_value>\r\n Debug.Print "Client #" & oClient.ClientId & ": " & oClient.RemoteHostIP & " (idle " & oClient.IdleSeconds & " seconds)"\r\n oClient.SendData "Broadcast message"\r\nNext\r\n\r\n\r\n---\r\n\r\nLast Updated: 2026-06-19\r\n