Skip to content

cWinsock UDP Programming Guide

📖 Table of Contents


Overview

UDP (User Datagram Protocol) is a connectionless, unreliable transmission protocol, suitable for scenarios requiring real-time performance and tolerating some data loss.

UDP Characteristics

  • Connectionless: No need to establish connection
  • Low latency: No connection overhead
  • Simple and efficient: Small protocol overhead
  • Broadcast support: Can send to multiple receivers simultaneously
  • Unreliable: Doesn't guarantee data arrival, ordering, or integrity
  • No flow control: May cause network congestion

Use Cases

  • Real-time gaming
  • Video streaming
  • Audio calls
  • DNS queries
  • Network discovery
  • IoT device communication

UDP Basic Programming

UDP Client

vb
' Declare UDP object
Private WithEvents m_oUdp As cWinsock

' Initialize
Private Sub Form_Load()
    Set m_oUdp = New cWinsock
    m_oUdp.Protocol = sckUDPProtocol
    m_oUdp.Bind 0 ' 0 means system auto-assigns port
    
    Debug.Print "UDP client bound to port: " & m_oUdp.LocalPort
End Sub

' Send data
Private Sub cmdSend_Click()
    ' Set remote address and port
    m_oUdp.RemoteHost = "127.0.0.1"
    m_oUdp.RemotePort = 8888
    
    ' Send data
    m_oUdp.SendData "Hello, UDP!"
    
    Debug.Print "Sent to " & m_oUdp.RemoteHost & ":" & m_oUdp.RemotePort
End Sub

' Receive data
Private Sub m_oUdp_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)
    Dim sData As String
    
    ' Receive data
    Client.GetData sData
    
    Debug.Print "Received data (" & bytesTotal & " bytes): " & sData
    Debug.Print "From: " & Client.RemoteHostIP & ":" & Client.RemotePort
End Sub

' Close
Private Sub Form_Unload(Cancel As Integer)
    On Error Resume Next
    m_oUdp.Close_
End Sub

UDP Server

vb
' Declare UDP server object
Private WithEvents m_oUdpServer As cWinsock

' Start server
Private Sub cmdStart_Click()
    Set m_oUdpServer = New cWinsock
    m_oUdpServer.Protocol = sckUDPProtocol
    m_oUdpServer.Bind 8888
    
    Debug.Print "UDP server bound to port: 8888"
End Sub

' Data arrival
Private Sub m_oUdpServer_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)
    Dim sData As String
    
    ' Receive data
    Client.GetData sData
    
    Debug.Print "Received from " & Client.RemoteHostIP & ":" & Client.RemotePort
    Debug.Print "Content: " & sData
    
    ' Reply
    Client.SendData "Reply: " & sData
    
    Debug.Print "Replied"
End Sub

' Close
Private Sub cmdStop_Click()
    m_oUdpServer.Close_
    Debug.Print "UDP server stopped"
End Sub

UDP Server Virtual Client

Overview

UDP is a connectionless protocol, but cWinsock creates virtual client objects for each different remote address:port combination, simulating connection behavior.

How It Works

First time receiving data from 192.168.1.100:5000

Create virtual client object, Tag = "192.168.1.100:5000"

Trigger ConnectionRequest event

Trigger DataArrival event

Can reply to that virtual client

Example Code

vb
Private WithEvents m_oUdpServer As cWinsock

' Start server
Private Sub cmdStart_Click()
    Set m_oUdpServer = New cWinsock
    m_oUdpServer.Protocol = sckUDPProtocol
    m_oUdpServer.Bind 8888
    
    Debug.Print "UDP server started"
End Sub

' New connection request (first time receiving data from some address:port)
Private Sub m_oUdpServer_ConnectionRequest(Client As cWinsock, ByRef DisConnect As Boolean)
    Debug.Print "New UDP client: " & Client.RemoteHostIP & ":" & Client.RemotePort
    Debug.Print "Tag: " & Client.Tag
    
    ' Can intercept here
    If IsInBlacklist(Client.RemoteHostIP) Then
        Debug.Print "Reject blacklist IP: " & Client.RemoteHostIP
        DisConnect = True
    End If
End Sub

' Data arrival
Private Sub m_oUdpServer_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)
    Dim sData As String
    
    ' Receive data
    Client.GetData sData
    
    Debug.Print "Data from " & Client.Tag & ": " & sData
    
    ' Reply directly to that virtual client
    Client.SendData "Echo: " & sData
End Sub

' Connection closed (virtual client timeout)
Private Sub m_oUdpServer_CloseEvent(Client As cWinsock)
    Debug.Print "UDP client " & Client.Tag & " disconnected"
    
    ' Update client list
    UpdateClientList
End Sub

' Update client list
Private Sub UpdateClientList()
    lstClients.Clear
    lblCount.Caption = m_oUdpServer.ClientCount
    
    Dim oClient As cWinsock
    For Each oClient In m_oUdpServer.Clients
        lstClients.AddItem oClient.Tag & " - " & oClient.RemoteHostIP & ":" & oClient.RemotePort
    Next
End Sub

Virtual Client Timeout Handling

vb
Private Sub tmrCleanup_Timer()
    Dim oClient As cWinsock
    Dim tSession As tSessionData
    
    For Each oClient In m_oUdpServer.Clients
        tSession = oClient.UserData
        
        ' Check timeout (5 minutes no activity)
        If DateDiff("s", tSession.LastActivity, Now) > 300 Then
            Debug.Print "Clean up timeout client: " & oClient.Tag
            oClient.Close_
        End If
    Next
End Sub

Private Sub m_oUdpServer_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)
    Dim sData As String
    Client.GetData sData
    
    ' Update activity time
    Dim tSession As tSessionData
    If IsEmpty(Client.UserData) Then
        tSession.FirstSeen = Now
    Else
        tSession = Client.UserData
    End If
    tSession.LastActivity = Now
    Client.UserData = tSession
    
    ' Process data...
    ProcessData Client, sData
End Sub

UDP Broadcast and Multicast

Broadcast

vb
' Broadcast to LAN
Private Sub cmdBroadcast_Click()
    ' Bind to any port
    m_oUdp.Bind 0
    
    ' Set broadcast address
    m_oUdp.RemoteHost = "255.255.255.255"
    m_oUdp.RemotePort = 9999
    
    ' Send broadcast message
    m_oUdp.SendData "Broadcast message"
    
    Debug.Print "Sent broadcast"
End Sub

' Receive broadcast
Private Sub m_oUdp_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)
    Dim sData As String
    Client.GetData sData
    
    Debug.Print "Received broadcast: " & sData
    Debug.Print "From: " & Client.RemoteHostIP & ":" & Client.RemotePort
End Sub

LAN Device Discovery

vb
' Send discovery request
Private Sub cmdDiscover_Click()
    m_oUdp.RemoteHost = "255.255.255.255"
    m_oUdp.RemotePort = 9999
    m_oUdp.SendData "DISCOVER_SERVERS"
End Sub

' Server responds to discovery
Private Sub m_oUdpServer_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)
    Dim sData As String
    Client.GetData sData
    
    If sData = "DISCOVER_SERVERS" Then
        ' Respond with own info
        Client.SendData "SERVER_INFO:" & GetLocalIP() & ":" & m_oUdpServer.LocalPort
    End If
End Sub

' Client collects responses
Private Sub m_oUdp_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)
    Dim sData As String
    Client.GetData sData
    
    If Left$(sData, 12) = "SERVER_INFO:" Then
        Dim sInfo As String
        sInfo = Mid$(sData, 13)
        
        Debug.Print "Discovered server: " & sInfo
        
        ' Add to list
        lstServers.AddItem sInfo
    End If
End Sub

Multicast (Groupcast)

vb
' Join multicast group
Private Sub JoinMulticastGroup(ByVal sGroupIP As String, ByVal lPort As Long)
    ' Note: cWinsock doesn't directly support multicast
    ' Need to use underlying socket API or cAsyncSocket
    
    ' Basic usage demonstrated here
    m_oUdp.Bind lPort
    m_oUdp.RemoteHost = sGroupIP
    m_oUdp.RemotePort = lPort
    
    Debug.Print "Joined multicast group: " & sGroupIP
End Sub

' Send to multicast group
Private Sub cmdSendMulticast_Click()
    m_oUdp.SendData "Multicast message"
    
    Debug.Print "Sent to multicast group"
End Sub

Advanced Features

✅ Reliable UDP (with Acknowledgment)

vb
' Reliable UDP sending
Private Type tReliablePacket
    Sequence As Long      ' Sequence number
    Total As Long         ' Total packets
    Index As Long         ' Current packet index
    Data As String       ' Data
    Acked As Boolean     ' Acknowledged
    Timestamp As Double  ' Send time
End Type

Private m_lSequence As Long
Private m_lWindowSize As Long

' Send data
Private Sub SendReliable(ByVal sData As String)
    Dim lChunkSize As Long
    lChunkSize = 1000 ' 1KB per packet
    
    Dim lTotalChunks As Long
    lTotalChunks = (Len(sData) \ lChunkSize) + 1
    
    Dim i As Long
    For i = 0 To lTotalChunks - 1
        Dim lStart As Long
        lStart = i * lChunkSize + 1
        
        Dim lEnd As Long
        lEnd = Min(lStart + lChunkSize - 1, Len(sData))
        
        Dim sChunk As String
        sChunk = Mid$(sData, lStart, lEnd - lStart + 1)
        
        ' Send packet
        m_oUdp.SendData "PKT:" & m_lSequence & ":" & lTotalChunks & ":" & i & ":" & sChunk
        
        Debug.Print "Sent packet " & i + 1 & "/" & lTotalChunks
        
        m_lSequence = m_lSequence + 1
        
        ' Control send rate
        If (i + 1) Mod m_lWindowSize = 0 Then
            Sleep 50 ' Wait when window full
        End If
    Next
End Sub

' Receive and acknowledge
Private Sub m_oUdp_DataArrival(Client As cWinsock, ByVal bytesTotal As Long)
    Dim sData As String
    Client.GetData sData
    
    If Left$(sData, 4) = "PKT:" Then
        ' Parse packet
        Dim sParts() As String
        sParts = Split(Mid$(sData, 5), ":")
        
        Dim lSeq As Long
        Dim lTotal As Long
        Dim lIndex As Long
        Dim sPayload As String
        
        lSeq = CLng(sParts(0))
        lTotal = CLng(sParts(1))
        lIndex = CLng(sParts(2))
        sPayload = sParts(3)
        
        Debug.Print "Received packet " & lIndex + 1 & "/" & lTotal & " (sequence: " & lSeq & ")"
        
        ' Send acknowledgment
        Client.SendData "ACK:" & lSeq & ":" & lIndex
        
        ' Process data...
        ProcessPacket lSeq, lIndex, lTotal, sPayload
    ElseIf Left$(sData, 4) = "ACK:" Then
        ' Received acknowledgment
        Dim sAckParts() As String
        sAckParts = Split(Mid$(sData, 5), ":")
        
        Dim lAckSeq As Long
        Dim lAckIndex As Long
        
        lAckSeq = CLng(sAckParts(0))
        lAckIndex = CLng(sAckParts(1))
        
        ' Mark as acknowledged
        MarkPacketAcked lAckSeq, lAckIndex
        
        Debug.Print "Received acknowledgment: " & lAckSeq & ":" & lAckIndex
    End If
End Sub

📊 Packet Reassembly

vb
' Packet reassembly
Private Type tReassemblyBuffer
    Packets() As String
    ReceivedCount As Long
    TotalCount As Long
End Type

Private m_oReassembly As Collection

' Initialize reassembly buffer
Private Sub InitReassembly(ByVal lSequence As Long, ByVal lTotal As Long)
    Dim tBuffer As tReassemblyBuffer
    
    ReDim tBuffer.Packets(0 To lTotal - 1) As String
    tBuffer.ReceivedCount = 0
    tBuffer.TotalCount = lTotal
    
    m_oReassembly.Add tBuffer, CStr(lSequence)
End Sub

' Add packet
Private Sub AddPacket(ByVal lSequence As Long, ByVal lIndex As Long, ByVal sData As String)
    Dim tBuffer As tReassemblyBuffer
    On Error Resume Next
    tBuffer = m_oReassembly(CStr(lSequence))
    On Error GoTo 0
    
    If tBuffer.TotalCount = 0 Then
        ' New sequence
        Debug.Print "New sequence: " & lSequence
    End If
    
    ' Store packet
    tBuffer.Packets(lIndex) = sData
    tBuffer.ReceivedCount = tBuffer.ReceivedCount + 1
    
    ' Update buffer
    If tBuffer.ReceivedCount = tBuffer.TotalCount Then
        ' All packets received, reassemble data
        Dim sComplete As String
        Dim i As Long
        
        For i = 0 To tBuffer.TotalCount - 1
            sComplete = sComplete & tBuffer.Packets(i)
        Next
        
        Debug.Print "Sequence " & lSequence & " reassembly complete, total size: " & Len(sComplete)
        
        ' Process complete data
        ProcessCompleteData sComplete
        
        ' Delete buffer
        m_oReassembly.Remove CStr(lSequence)
    Else
        ' Update buffer
        m_oReassembly.Remove CStr(lSequence)
        m_oReassembly.Add tBuffer, CStr(lSequence)
    End If
End Sub

🕐 Timeout Retransmission

vb
' Timeout retransmission mechanism
Private Type tPendingPacket
    Sequence As Long
    Index As Long
    Data As String
    Timestamp As Double
    RetryCount As Long
End Type

Private m_oPendingPackets As Collection
Private Const PACKET_TIMEOUT As Double = 5 ' 5 second timeout
Private Const MAX_RETRIES As Long = 3

' Send packet with timeout
Private Sub SendWithTimeout(ByVal lSeq As Long, ByVal lIdx As Long, ByVal sData As String)
    ' Send data
    m_oUdp.SendData "PKT:" & lSeq & ":" & lIdx & ":" & sData
    
    ' Add to pending list
    Dim tPending As tPendingPacket
    tPending.Sequence = lSeq
    tPending.Index = lIdx
    tPending.Data = sData
    tPending.Timestamp = Timer
    tPending.RetryCount = 0
    
    m_oPendingPackets.Add tPending, CStr(lSeq) & ":" & CStr(lIdx)
    
    Debug.Print "Sent packet " & lSeq & ":" & lIdx & ", waiting for acknowledgment..."
End Sub

' Check timeout
Private Sub tmrTimeout_Timer()
    Dim i As Long
    For i = m_oPendingPackets.Count To 1 Step -1
        Dim tPending As tPendingPacket
        tPending = m_oPendingPackets(i)
        
        ' Check if timeout
        If Timer - tPending.Timestamp > PACKET_TIMEOUT Then
            If tPending.RetryCount < MAX_RETRIES Then
                ' Retransmit
                Debug.Print "Packet " & tPending.Sequence & ":" & tPending.Index & " timeout, retrying..."
                
                ' Resend
                m_oUdp.SendData "PKT:" & tPending.Sequence & ":" & tPending.Index & ":" & tPending.Data
                
                ' Update retry count and time
                tPending.RetryCount = tPending.RetryCount + 1
                tPending.Timestamp = Timer
                
                m_oPendingPackets.Remove i
                m_oPendingPackets.Add tPending, CStr(tPending.Sequence) & ":" & CStr(tPending.Index)
            Else
                ' Max retries reached, give up
                Debug.Print "Packet " & tPending.Sequence & ":" & tPending.Index & " exceeded max retries, giving up"
                
                m_oPendingPackets.Remove i
            End If
        End If
    Next
End Sub

' Acknowledge packet
Private Sub AckPacket(ByVal lSeq As Long, ByVal lIdx As Long)
    Dim sKey As String
    sKey = CStr(lSeq) & ":" & CStr(lIdx)
    
    On Error Resume Next
    m_oPendingPackets.Remove sKey
    On Error GoTo 0
    
    Debug.Print "Acknowledged packet " & lSeq & ":" & lIdx
End Sub

Common Issues

❓ Issue 1: UDP Packet Loss

Symptom: Sent data not received by peer

Cause: UDP is unreliable transmission, packets may be lost

Solution: Implement acknowledgment and retransmission mechanism (as shown above)


❓ Issue 2: Packet Out of Order

Symptom: Received packets not in same order as sent

Cause: UDP doesn't guarantee ordering

Solution: Implement sequence number and reassembly mechanism


❓ Issue 3: Duplicate Packets

Symptom: Receiving duplicate packets

Cause: Caused by retransmission

Solution: Deduplicate by sequence number

vb
Private Function IsDuplicate(ByVal lSequence As Long) As Boolean
    Static lLastSequence As Long
    
    If lSequence <= lLastSequence Then
        IsDuplicate = True
    Else
        IsDuplicate = False
        lLastSequence = lSequence
    End If
End Function

❓ Issue 4: Broadcast Failure

Symptom: No response after sending broadcast

Cause: Firewall blocking broadcast

Solution: Configure firewall or use specific port

vb
' Try different broadcast addresses
m_oUdp.RemoteHost = "192.168.1.255" ' Subnet broadcast
m_oUdp.SendData "Broadcast"

❓ Issue 5: Virtual Client Not Cleaned

Symptom: UDP server client list keeps growing

Cause: UDP connectionless, cannot automatically detect client disconnect

Solution: Implement timeout cleanup mechanism

vb
Private Sub tmrCleanup_Timer()
    Dim oClient As cWinsock
    Dim tSession As tSessionData
    
    For Each oClient In m_oUdpServer.Clients
        tSession = oClient.UserData
        
        ' Check timeout
        If DateDiff("s", tSession.LastActivity, Now) > 300 Then
            Debug.Print "Clean up timeout client: " & oClient.Tag
            oClient.Close_
        End If
    Next
End Sub

Last Updated: 2026-01-09

VB6 and LOGO copyright of Microsoft Corporation