Skip to content

Packet Protocol and Heartbeat Mechanism

📦💓 Built-in protocol to solve TCP sticky packet/fragmentation issues, and intelligent heartbeat to keep connections alive

📖 Table of Contents


Overview

TCP is a stream protocol without message boundaries — data sent continuously by the sender may be received multiple times by the receiver (fragmentation), or multiple messages may be received at once as concatenated data (sticky packets). cWinsock's built-in packet protocol cPacketProtocol and intelligent heartbeat cHeartbeat automatically solve these problems:

  • Packet Protocol: Three built-in protocols, automatic packet/unpacket, ensuring each receive is a complete message
  • Heartbeat Mechanism: Embedded timer automatic drive, server timeout detection + client intelligent keepalive

TCP Sticky Packet and Fragmentation Issues

What are Sticky Packets/Fragmentation?

PhenomenonTermDescription
Data from one Send arrives in multiple ReceivesFragmentationSent 1000 bytes, first receive 300, then 700
Data from multiple Sends arrives in one ReceiveSticky PacketSent 3 messages continuously, received as concatenated data
Both mixedMost CommonReceived data is both incomplete and mixed with next message's start

Visual Diagram

Application layer sends: [Msg1][Msg2][Msg3]
                ↓ TCP stream transmission (no boundaries)
Receiver may receive:
  Case 1 (Fragmentation):  [Msg1 part1]  [Msg1 part2+Msg2 part1]  [Msg2 part2+Msg3]
  Case 2 (Sticky Packet): [Msg1+Msg2]  [Msg3]
  Case 3 (Mixed):          [Msg1 part1]  [Msg1 part2+Msg2]  [Msg3 part1]  [Msg3 part2]
  Ideal case (Rare):       [Msg1]  [Msg2]  [Msg3]

cPacketProtocol's Solution

Define clear boundaries in data, restoring boundary-less byte streams into bounded messages:

Raw TCP byte stream (no boundaries):
  [Msg1 part1][Msg1 part2+Msg2 part1][Msg2 part2]
                        ↓ cPacketProtocol.Decode()
Complete messages:
  [Msg1 Complete] → Trigger MessageArrival
  [Msg2 Complete] → Trigger MessageArrival

Packet Protocol

Three Protocol Types Comparison

Protocol TypePrincipleFragmentation HandlingSticky Packet HandlingPros/Cons
ppLengthHeaderHeader indicates message body lengthCache if length insufficient, extract when data arrivesCut one when length sufficient, continue parsing remainderRecommended. Not dependent on data content, no message length limit
ppDelimiterDelimiter marks message endCache if delimiter not foundCut one when delimiter found, continue searchingSimple, but delimiter cannot appear in message body
ppFixedLengthFixed message lengthCache if less than fixed lengthCut one when fixed length reachedOnly for fixed-length message scenarios

4-byte little-endian length header protocol is the most universal choice:

  • Not dependent on special characters appearing in data content (delimiter protocol's weakness)
  • No single message length limit (fixed-length protocol's weakness)
  • Each message has its own length, receiver knows exactly how many bytes to read

ppDelimiter - Delimiter Protocol

Uses specified character/string as message boundary marker.

Use Case: Text protocols, line-based command protocols (e.g., chat, HTTP headers)

vb
' Configuration
m_oServer.PacketProtocol = ppDelimiter
m_oServer.Delimiter = vbCrLf  ' Newline delimiter

' Send automatically appends delimiter
Client.SendData "Hello"  ' Actually sends: "Hello" + vbCrLf

' Receive automatically removes delimiter
Private Sub m_oServer_MessageArrival(Client As cWinsock, ByVal bytesTotal As Long)
    Debug.Print "Complete message: " & Client.GetDataText()  ' "Hello"
End Sub

Common Delimiters:

DelimiterConstantUse Case
\r\nvbCrLfLine-based text protocol
\nvbLfUnix-style line protocol
\0vbNullCharC string style
Custom string"<EOF>"Custom protocol

Note: Delimiter cannot appear in message body, otherwise messages will be incorrectly split.


ppFixedLength - Fixed Length Protocol

Each message has fixed length, suitable for structured data with known length.

Use Case: Status packets, sensor data, fixed-format messages

vb
' Configuration
m_oServer.PacketProtocol = ppFixedLength
m_oServer.FixedLength = 256  ' Each message fixed 256 bytes

' Send: Less than 256 bytes will be zero-padded, more than 256 bytes will error
Client.SendData myData

Note: Data exceeding length will directly error (won't silently truncate).


Add length information in message header, most universal and recommended protocol.

Use Case: Binary protocols, variable-length messages, any scenario needing reliable transmission

vb
' Configuration
m_oServer.PacketProtocol = ppLengthHeader
m_oServer.HeaderBytes = 4                ' 4-byte length header (supports max ~4GB)
m_oServer.HeaderEndian = eeLittleEndian  ' Little-endian

' Send automatically adds length header
Client.SendData "Hello"  ' Actually sends: [4-byte length=5] + "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()  ' 100% is one complete message
End Sub

HeaderBytes Options:

ValueTypeMax Message LengthDescription
2Unsigned Integer65,535 bytes (~64KB)Small message scenarios, saves bandwidth
4Unsigned Long2,147,483,647 bytes (~2GB)General scenarios, recommended

HeaderEndian Byte Order:

ValueDescriptionUse Case
eeLittleEndianLittle-endian (default)x86/x64 platform internal communication
eeBigEndianBig-endian (network byte order)Communication with Java/C server

Security Limit Properties

Prevent malicious packets from exhausting memory, added 2026-06-09:

MaxPacketSize

Single packet maximum size limit, prevents malicious oversized packet declarations from exhausting memory.

vb
Property Get MaxPacketSize() As Long
Property Let MaxPacketSize(ByVal Value As Long)
  • Default: 1MB (1048576 bytes)
  • Function: During length header protocol parsing, if declared message length exceeds this value, directly error and discard
  • Applicable Protocol: ppLengthHeader
vb
' Adjust max packet limit
m_oServer.MaxPacketSize = 524288  ' 512KB

' New clients automatically inherit this configuration

MaxBufferSize

Buffer accumulation upper limit, prevents large numbers of incomplete packets slowly consuming memory.

vb
Property Get MaxBufferSize() As Long
Property Let MaxBufferSize(ByVal Value As Long)
  • Default: 4MB (4194304 bytes)
  • Function: Check before Decode merge buffer, error if exceeded
  • Applicable Protocol: All protocols
vb
' Adjust buffer upper limit
m_oServer.MaxBufferSize = 8388608  ' 8MB

Overflow Behavior

Overflow TypeBehavior
Single packet exceeds MaxPacketSizeThrow explicit error message, discard buffer
Accumulation exceeds MaxBufferSizeThrow explicit error message, discard buffer
Data too long (FixedLength)Throw error (won't silently truncate)

Event Model

Protocol Mode vs No-Protocol Mode Difference

ModeTrigger EventDescription
No Protocol (ppNone)DataArrivalRaw byte stream, may be incomplete or sticky
With ProtocolMessageArrivalEach time guaranteed to be one complete message

Key Rule: In protocol mode only MessageArrival is triggered, DataArrival is not triggered, avoiding duplicate reads of same data by two events.

MessageArrival Event

vb
Private Sub object_MessageArrival(Client As cWinsock, ByVal bytesTotal As Long)
ParameterTypeDescription
ClientcWinsockClient object receiving message
bytesTotalLongComplete message byte count

Usage Example

vb
' Set length header protocol
m_oServer.PacketProtocol = ppLengthHeader
m_oServer.HeaderBytes = 4
m_oServer.HeaderEndian = eeLittleEndian

' Receive complete message
Private Sub m_oServer_MessageArrival(Client As cWinsock, ByVal bytesTotal As Long)
    ' Buffer now contains complete message, 100% complete
    Dim sData As String
    sData = Client.GetDataText()
    Debug.Print "Complete message: " & sData
End Sub

Difference from DataArrival

EventTrigger TimingData IntegrityUse Case
DataArrivalEach time raw data receivedMay be fragmented or sticky dataNo-protocol mode
MessageArrivalAfter protocol parses complete messageGuaranteed to be one complete messageProtocol mode

Intelligent Heartbeat Mechanism

cWinsock's built-in cHeartbeat heartbeat manager, embedded cTimer automatic drive, no external timer needed.

Server: Timeout Detection

Server periodically checks all clients' idle time, automatically disconnects zombie connections after timeout.

vb
' Configuration
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"
End Sub

Client: Heartbeat Keepalive

Client periodically sends heartbeat packets to keep connection alive. Has intelligent skip mechanism — skips heartbeat when data is being sent/received, saving bandwidth.

vb
' Configuration
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 Sub

Custom Heartbeat Packet

vb
' 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 = baHB

Heartbeat and Protocol Consistency

Heartbeat data is sent through protocol encoding, won't pollute protocol state machine. That is:

  • Heartbeat packets sent through SendData, go through protocol Encode
  • Receiver heartbeat data goes through protocol Decode
  • Heartbeat won't cause sticky packet/fragmentation state confusion

Working Principle

  1. Heartbeat manager embedded cTimer, triggers Tick every 10 seconds
  2. Server: Checks all clients' IdleSeconds, triggers ClientTimeout and auto-disconnects if timeout
  3. Client: If idle exceeds HeartbeatInterval sends heartbeat packet, intelligently skips when data is sent/received
  4. Each send/receive automatically resets LastActivityTime
PropertyTypeRead/WriteDescription
AutoHeartbeatBooleanRWEnable/Disable automatic heartbeat
HeartbeatTimeoutLongRWServer timeout seconds (default 120)
HeartbeatIntervalLongRWClient heartbeat interval seconds (default 50)
HeartbeatDataByte()RWHeartbeat packet content (default single byte 0)
IdleSecondsLongROCurrent idle seconds

UDP Protocol Support

UDP clients also support packet protocols. UDP is a datagram protocol (naturally has boundaries), but protocol mode can still be used for:

  • Custom message format processing
  • Sharing protocol logic with TCP side
  • Utilizing security limit properties
vb
' UDP server set protocol
m_oUdp.PacketProtocol = ppLengthHeader
m_oUdp.HeaderBytes = 4
m_oUdp.MaxPacketSize = 65536  ' UDP single packet usually doesn't exceed 64KB

' UDP virtual client automatically inherits protocol configuration
Private Sub m_oUdp_MessageArrival(Client As cWinsock, ByVal bytesTotal As Long)
    Dim sData As String
    sData = Client.GetDataText()
    Debug.Print "UDP complete message: " & sData
End Sub

Complete Examples

TCP Server + Length Header Protocol + Heartbeat

vb
Private WithEvents m_oServer As cWinsock

Private Sub Form_Load()
    Set m_oServer = New cWinsock
    
    ' Set packet protocol (Recommended: length header protocol)
    m_oServer.PacketProtocol = ppLengthHeader
    m_oServer.HeaderBytes = 4
    m_oServer.HeaderEndian = eeLittleEndian
    m_oServer.MaxPacketSize = 1048576   ' 1MB
    m_oServer.MaxBufferSize = 4194304   ' 4MB
    
    ' Set heartbeat
    m_oServer.AutoHeartbeat = True
    m_oServer.HeartbeatTimeout = 120    ' 2 minutes timeout
    
    ' Start server
    m_oServer.Listen 8080
    Debug.Print "Server started"
End Sub

Private Sub m_oServer_ConnectionRequest(Client As cWinsock, ByRef DisConnect As Boolean)
    Debug.Print "New client: " & Client.RemoteHostIP & ":" & Client.RemotePort
    ' New clients automatically inherit protocol and heartbeat configuration
End Sub

Private Sub m_oServer_MessageArrival(Client As cWinsock, ByVal bytesTotal As Long)
    ' 100% is complete message
    Dim sData As String
    sData = Client.GetDataText()
    Debug.Print "[" & Client.Tag & "] " & sData
    
    ' Echo
    Client.SendData "Echo: " & sData
End Sub

Private Sub m_oServer_ClientTimeout(Client As cWinsock)
    Debug.Print "Client timeout: " & Client.Tag
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)
    On Error Resume Next
    m_oServer.Close_
End Sub

TCP Client + Length Header Protocol + Heartbeat

vb
Private WithEvents m_oClient As cWinsock

Private Sub Form_Load()
    Set m_oClient = New cWinsock
    
    ' Set packet protocol (Must be consistent with server)
    m_oClient.PacketProtocol = ppLengthHeader
    m_oClient.HeaderBytes = 4
    m_oClient.HeaderEndian = eeLittleEndian
    
    ' Set heartbeat
    m_oClient.AutoHeartbeat = True
    m_oClient.HeartbeatInterval = 50    ' 50 seconds interval
    
    ' Connect
    m_oClient.Connect "127.0.0.1", 8080
End Sub

Private Sub m_oClient_Connect(Client As cWinsock)
    Debug.Print "Connected"
    Client.SendData "Hello, Server!"
End Sub

Private Sub m_oClient_MessageArrival(Client As cWinsock, ByVal bytesTotal As Long)
    Dim sData As String
    sData = Client.GetDataText()
    Debug.Print "Received: " & sData
End Sub

Private Sub m_oClient_HeartbeatSent(Client As cWinsock)
    Debug.Print "Heartbeat sent"
End Sub

Private Sub Form_Unload(Cancel As Integer)
    On Error Resume Next
    m_oClient.Close_
End Sub

Chat Server + Delimiter Protocol

vb
Private WithEvents m_oServer As cWinsock

Private Sub Form_Load()
    Set m_oServer = New cWinsock
    
    ' Use newline as message delimiter
    m_oServer.PacketProtocol = ppDelimiter
    m_oServer.Delimiter = vbCrLf
    
    ' Heartbeat keepalive
    m_oServer.AutoHeartbeat = True
    m_oServer.HeartbeatTimeout = 180
    
    m_oServer.Listen 9090
End Sub

Private Sub m_oServer_MessageArrival(Client As cWinsock, ByVal bytesTotal As Long)
    Dim sMsg As String
    sMsg = Client.GetDataText()
    
    ' Broadcast to all clients
    Dim oClient As cWinsock
    For Each oClient In m_oServer.Clients
        If Not oClient Is Client Then
            oClient.SendData "[" & Client.Tag & "] " & sMsg
        End If
    Next
End Sub

Best Practices

1. Choose Appropriate Protocol Type

Protocol TypeUse CasePros/Cons
ppLengthHeaderBinary protocol, variable-length messagesMost universal, recommended
ppDelimiterText protocol (chat, command-line style)Simple and intuitive, but data cannot contain delimiter
ppFixedLengthFixed-format messages (status packets, sensor data)Fastest parsing, but not flexible

2. Use MessageArrival in Protocol Mode

vb
' ✅ Correct: Use MessageArrival in protocol mode
Private Sub m_oServer_MessageArrival(Client As cWinsock, ByVal bytesTotal As Long)
    Dim sData As String
    sData = Client.GetDataText()  ' Guaranteed to be complete message
End Sub

' ❌ Wrong: Use DataArrival in protocol mode
' DataArrival won't trigger in protocol mode

3. Length Header Protocol Byte Order

vb
' Use big-endian when communicating with C/Java server
m_oServer.HeaderEndian = eeBigEndian

' Can use little-endian for pure VB6 internal communication (default)
m_oServer.HeaderEndian = eeLittleEndian

4. Configure Security Limits

vb
' Adjust security limits based on business requirements
m_oServer.MaxPacketSize = 524288   ' 512KB, max single packet
m_oServer.MaxBufferSize = 8388608  ' 8MB, max buffer

5. Configure Server Protocol Before Listen

vb
' ✅ Correct: Set protocol before Listen
m_oServer.PacketProtocol = ppLengthHeader
m_oServer.HeaderBytes = 4
m_oServer.Listen 8080

' New clients automatically inherit server configuration, create independent protocol instances

6. Heartbeat Cooperates with Protocol

Heartbeat packets go through protocol encoding, won't pollute protocol state machine, no need to manually filter heartbeats.


FAQ

❓ Why use packet protocol?

TCP is a stream protocol without message boundaries. Without using protocol, DataArrival may receive incomplete or sticky data, requiring manual stitching/splitting, prone to errors. After using packet protocol, MessageArrival triggers with one complete message each time, developer doesn't need to care about underlying byte stream merging/splitting.

❓ What's the difference between MaxPacketSize and MaxBufferSize?

  • MaxPacketSize: Maximum length of single message, for declared message body length in length header protocol
  • MaxBufferSize: Receive buffer accumulation upper limit, prevents large numbers of incomplete packets slowly consuming memory

❓ Will DataArrival still trigger in protocol mode?

No. In protocol mode only MessageArrival is triggered, avoiding same data being read twice by two events. No-protocol mode still triggers DataArrival.

❓ Will heartbeat packets affect protocol parsing?

No. Heartbeat data is sent and received through protocol encoding, won't pollute protocol state machine.

❓ Does UDP need packet protocol?

UDP naturally has message boundaries, doesn't need packet protocol to solve sticky packet issues. But UDP clients also support protocol mode, can be used for unified message format, utilizing security limit properties, etc.

❓ How large a message can 2-byte length header transmit?

2-byte header can represent 0~65535 (max about 64KB). Exceeding 65535 bytes will error. Recommend using 4-byte header for large data.


DocumentDescription
Properties ReferenceDetailed description of protocol and heartbeat related properties
Events ReferenceMessageArrival, ClientTimeout and other events
Methods ReferenceGetDataText, GetDataByteArray and other methods
TCP ProgrammingTCP client and server programming guide
Best PracticesSolutions for common scenarios and performance optimization recommendations

Last Updated: 2026-06-09

VB6 and LOGO copyright of Microsoft Corporation