Click here to Skip to main content
Licence 
First Posted 7 Jun 2005
Views 172,563
Bookmarked 55 times

TinyUDP - Simple UDP Client/Server Components for .NET

By | 7 Jun 2005 | Article
Simple UDP client/server components for .NET 1.1.

Introduction

This article was written in the course of implementing a simple method for a Windows service to communicate status information to a front-end administration application. This article was written using the excellent article UDP send and receive using threads in VB.NET by Kumudu Gunasekara for inspiration and 'spiritual guidance', as well as some nifty ideas. Kumudu's article is definitely worth reading.

Background

I decided to implement a simple UDP client/server system for simple communication between my Windows service and the administration program for a variety of reasons:

  1. UDP is lightweight and fast compared to other protocols, such as TCP. This was important to me, as my Windows service needed to maintain high performance.
  2. UDP is connectionless, which means that it can fire off a message and immediately free server-side network resources. Incidentally, this also makes UDP one of the easiest protocols to write a client/server application for.
  3. UDP preserves message boundaries transmitting entire messages at once.

Some of the drawbacks of UDP are:

  1. UDP does not guarantee delivery or provide for acknowledgment of receipt of messages. In this instance, that was perfectly acceptable since I was simply passing the status data from the Windows service to the UI layer.
  2. UDP has practical limits on how much data can be sent in a single message - usually limited to 1500 Bytes per message or less. Again, this limitation worked well given my scenario - I would normally not be passing more than 100 bytes per message.

Using the code

The code is pretty straightforward and well documented. There are two components: Tiny.UDP.TinyServer and Tiny.UDP.TinyClient. They are .NET 1.1 components, so they can be added to your Toolbox and dropped right in your Windows Forms; or you can reference them (as I did in the sample applications) by creating objects in the code. The code to create a server looks like this:

' Initialize a TinyServer Object
Dim server As New TinyServer

' Set it for UDP and assign the destination end point
server.Protocol = ProtocolType.Udp
server.ClientAddress = IPAddress.Parse("127.0.0.1")
server.ClientPort = 8088

' Set the Encoding Type and Send the Message
server.Encode = EncodingType.ASCII

All we're doing here is:

  1. Creating the TinyServer object.
  2. Setting the communications protocol (currently only UDP is supported), client IP address and client port.
  3. And finally, setting the message encoding type (ASCII, UNICODE, UTF7, UTF8 and all others are supported).

Next we set up the TinyClient:

' Define a TinyClient object
Dim WithEvents client As TinyClient

' Create a client object
client = New TinyClient

' Set the inbound client port
client.ClientPort = 8088

' Set the encoding type and protocol
client.Encode = EncodingType.ASCII
client.Protocol = ProtocolType.Udp

Again, it's a simple matter to set up a client:

  1. Define and create a new TinyClient object. Notice it is declared WithEvents.
  2. Set the inbound client port number.
  3. Set the encoding type and protocol to match the TinyServer that we created.

That's a simple UDP client and server with just 10 lines of code! (Not counting comments of course.) Finally, we start the client running with the Start() method:

client.Start()

and send messages from the server with the SendMessage() method:

server.SendMessage ("This is a UDP Message sent by TinyServer.")

The TinyClient object was declared WithEvents because it implements two events: BeforeReceive and AfterReceive. BeforeReceive is fired immediately before receiving data off the wire. AfterReceive is fired immediately after the client finishes receiving data. You can set up your own subroutines to handle these events as you see fit. Other events may be added later; but for now I decided those two were the most important to get implemented.

How does it work?

If you look into the code, you will see that the TinyServer simply creates a System.Net.Sockets.UdpClient, opens a connection, and fires off your message when you call the SendMessage() method. Very simple. The client is where the fun begins.

On the client side, the Start() method actually fires off a worker thread that in turn starts its own System.Net.Sockets.UdpClient and waits for data. We set it off on a separate worker thread because the Receive() method blocks the current thread until it completes - and we don't need it locking up our UI. Once a message is received by the worker thread, the thread exits immediately, so we start a new worker thread to continue waiting for the next message.

Because these events are fired from the worker thread, you'll notice in the sample program that I check Me.InvokeRequired on the client form before I update it. This is necessary because of the nature of multi-threaded apps; never update the UI from a worker thread, always check InvokeRequired and use Invoke if it is True.

Finally, when we finish, fire the client.Stop() method to stop the worker thread and cleanly dispose off the UDPClient.

Points of interest

As mentioned previously, this works best on a local machine or on locally networked computers; for instance, when communicating non-critical information between layers of a locally installed application. It also has the potential for chat applications, which I'm sure has been done to death by now :) My main goal in designing this was to create a reusable, lightweight set of components that could be used to allow Windows services to easily communicate with the front-end client applications without jumping through hoops.

Enjoy!

History

  • June 8th, 2005 - version 0.8.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

tupacs01

Web Developer

United States United States

Member

Database Admin (MCDBA) and Programmer with 15+ years' experience in data warehousing, application design and development, and systems integration.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
QuestionCan't receive message PinmemberAl Najjar15:14 21 Dec '11  
AnswerRe: Can't receive message PinmemberFilip Mestric9:55 2 Feb '12  
Questionmake receiver in asp.net Pinmemberdavismu19:54 1 Jul '11  
Generalwhen to call the InitializeThread() PinmemberKHelmi9:00 2 Jun '10  
QuestionWhat kind of license has this code? Pinmemberunican10:36 9 Dec '08  
Questionhow to receive msg when receiver is behind router PinmemberMember 468623916:09 11 Feb '08  
GeneralTinyUDP seriously flawed Pinmembermarantz6:41 14 Nov '07  
Generaludp socket to accept data and write it to a db Pinmemberdaver564:18 4 Jul '07  
GeneralUDP over GPRS (push to client) Pinmemberdjgann12:33 17 Apr '07  
GeneralRe: UDP over GPRS (push to client) PinmemberMember 292441817:15 19 Mar '09  
GeneralThanks for the complements PinmemberKumudu Gunasekara17:32 24 Mar '07  
GeneralI need a source code that view installed applications and run them. PinmemberMjRazzaghi4:22 2 Jan '07  
Questionhelp PinmemberGigi Carlino6:14 26 Oct '06  
GeneralHelp ... Create new Form from worker thread Pinmemberryan@theglenns.co.za23:26 19 Sep '06  
GeneralMemory Usage in Task Manager Pinmemberbrembot5:41 2 Aug '06  
GeneralHELP I NEED A GOOD UDP SOURCE PinmemberFulmine4:50 23 Jan '06  
GeneralProgram not closing; tried lots of things... Pinmemberdaniellus12:29 3 Jan '06  
GeneralRe: Program not closing; tried lots of things... PinmemberNairbNilpop16:30 1 Feb '06  
GeneralRe: Program not closing; tried lots of things... Pinmemberawdrgftdesq5:32 19 Sep '06  
GeneralMultithreading start/stop question Pinmemberdavidm9910:09 1 Dec '05  
QuestionInvoke PinmemberLost-Ha[n]f-PHP1:31 24 Nov '05  
AnswerRe: Invoke Pinmembertupacs013:36 28 Nov '05  
GeneralConfusing naming convention Pinmembermeraydin10:25 15 Nov '05  
GeneralRe: Confusing naming convention Pinmembertupacs013:40 28 Nov '05  
GeneralRe: Fix for naming convention and exit bug PinmemberDanilo Corallo21:45 20 Feb '07  
I've changed the names of both classes to their reverse... I've also made a fix for the exiting problem. I hope it helps someone... Poke tongue | ;-P
Here the code (remember to rename the filename too):
TinyClient.vb
Imports System.Net.Sockets
Imports System.Net
Imports System.Text
Imports System.ComponentModel
 
Namespace Tiny.UDP
Public Class TinyClient
Inherits System.ComponentModel.Component
 
#Region " Component Designer generated code "
 
Public Sub New(ByVal Container As System.ComponentModel.IContainer)
MyClass.New()
 
'Required for Windows.Forms Class Composition Designer support
Container.Add(Me)
End Sub
 
Public Sub New()
MyBase.New()
 
'This call is required by the Component Designer.
InitializeComponent()
 
'Add any initialization after the InitializeComponent() call
 
End Sub
 
'Component overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
 
'Required by the Component Designer
Private components As System.ComponentModel.IContainer
 
'NOTE: The following procedure is required by the Component Designer
'It can be modified using the Component Designer.
'Do not modify it using the code editor.
Private Sub InitializeComponent()
components = New System.ComponentModel.Container
End Sub
 
#End Region
 
' Default property values
Private _Protocol As ProtocolType = ProtocolType.Udp
Private _ServerAddress As IPAddress = IPAddress.Any
Private _ServerPort As Integer = 0
Private _data As Byte() = New Byte() {}
Private _Encode As EncodingType
 
_
Public Property Protocol() As ProtocolType
Get
Return (_Protocol)
End Get
Set(ByVal Value As ProtocolType)
If (Value = ProtocolType.Udp) Then
_Protocol = Value
Else
Throw New ProtocolNotSupportedException
End If
End Set
End Property
 
_
Public Property Server() As IPEndPoint
Get
Return New IPEndPoint(_ServerAddress, _ServerPort)
End Get
Set(ByVal Value As IPEndPoint)
_ServerAddress = Value.Address
_ServerPort = Value.Port
End Set
End Property
 
_
Public Property ServerAddress() As IPAddress
Get
Return _ServerAddress
End Get
Set(ByVal Value As IPAddress)
_ServerAddress = Value
End Set
End Property
 
_
Public Property ServerPort() As Integer
Get
Return _ServerPort
End Get
Set(ByVal Value As Integer)
_ServerPort = Value
End Set
End Property
 
_
Public Property Encode() As EncodingType
Get
Return (_Encode)
End Get
Set(ByVal Value As EncodingType)
_Encode = Value
End Set
End Property
 
Public Sub SendMessage(ByVal message As String)
' Encode message per settings
Select Case Encode
Case EncodingType.Default
_data = Encoding.Default.GetBytes(message)
Case EncodingType.ASCII
_data = Encoding.ASCII.GetBytes(message)
Case EncodingType.Unicode
_data = Encoding.Unicode.GetBytes(message)
Case EncodingType.UTF7
_data = Encoding.UTF7.GetBytes(message)
Case EncodingType.UTF8
_data = Encoding.UTF8.GetBytes(message)
Case Else
Throw New BadEncodingException
End Select
' Send the message
Try
Select Case Protocol
Case ProtocolType.Udp
SendUDPMessage(_data)
End Select
Catch ex As Exception
Throw ex
End Try
End Sub
 
Private Function SendUDPMessage(ByVal _data As Byte()) As Integer
' Create a UDP Server and send the message, then clean up
Dim _UDPClient As UdpClient = Nothing
Dim ReturnCode As Integer
Try
_UDPClient = New UdpClient
ReturnCode = 0
_UDPClient.Connect(Server)
ReturnCode = _UDPClient.Send(_data, _data.Length)
Catch ex As Exception
Throw ex
Finally
If Not (_UDPClient Is Nothing) Then
_UDPClient.Close()
End If
End Try
Return ReturnCode
End Function
 
End Class
 
End Namespace

TinyServer.vb
Imports System.Net.Sockets
Imports System.Net
Imports System.Text
Imports System.Threading
Imports System.ComponentModel
 
Namespace Tiny.UDP
Public Class TinyServer
Inherits System.ComponentModel.Component
 
#Region " Component Designer generated code "
 
Public Sub New(ByVal Container As System.ComponentModel.IContainer)
MyClass.New()
 
'Required for Windows.Forms Class Composition Designer support
Container.Add(Me)
End Sub
 
Public Sub New()
MyBase.New()
 
'This call is required by the Component Designer.
InitializeComponent()
 
'Add any initialization after the InitializeComponent() call
 
End Sub
 
'Component overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
 
'Required by the Component Designer
Private components As System.ComponentModel.IContainer
 
'NOTE: The following procedure is required by the Component Designer
'It can be modified using the Component Designer.
'Do not modify it using the code editor.
Private Sub InitializeComponent()
components = New System.ComponentModel.Container
End Sub
 
#End Region
 
' Default Property values
Private _Protocol As ProtocolType = ProtocolType.Udp
Private _ThreadReceive As Thread
Private _ClientPort As Integer = 0
Private _Message As String = ""
Private _Encode As EncodingType = EncodingType.Default
Private _UDPClient As UdpClient
Private _Client As New IPEndPoint(IPAddress.Any, 0)
Private _BytesReceived As Integer = 0
Private _closing As Boolean = False
 
_
Public Event BeforeReceive As EventHandler
 
_
Public Event AfterReceive As EventHandler
 
_
Public Property Encode() As EncodingType
Get
Return (_Encode)
End Get
Set(ByVal Value As EncodingType)
_Encode = Value
End Set
End Property
 
_
Public ReadOnly Property BytesReceived() As Integer
Get
Return (_BytesReceived)
End Get
End Property
 
_
Public ReadOnly Property Message() As String
Get
Return (_Message)
End Get
End Property
 
_
Public Property Client() As IPEndPoint
Get
Return _Client
End Get
Set(ByVal Value As IPEndPoint)
_Client = Value
End Set
End Property
 
_
Public Property ServerPort() As Integer
Get
Return (_ClientPort)
End Get
Set(ByVal Value As Integer)
_ClientPort = Value
End Set
End Property
 
_
Public Property Protocol() As ProtocolType
Get
Return (_Protocol)
End Get
Set(ByVal Value As ProtocolType)
_Protocol = Value
End Set
End Property
 
Public Sub Receive()
' Clear the Message property
_Message = ""
' Raise the BeforeReceive event
RaiseEvent BeforeReceive(Me, New EventArgs)
' Receive our UDP data
Dim _data As Byte()
Try
Select Case Protocol
Case ProtocolType.Udp
_data = _UDPClient.Receive(_Client)
_BytesReceived = _data.Length
Case Else
Throw New ProtocolNotSupportedException
End Select
Catch ex As Exception
If Not _closing Then
Throw ex
Else
Exit Sub
End If
Finally
' The thread finished blocking, and ended, so we start again
If Not _closing Then InitializeThread()
End Try
' Encode the data per the Encode property
Dim _strdata As String
Select Case Encode
Case EncodingType.Default
_strdata = System.Text.Encoding.Default.GetString(_data)
Case EncodingType.ASCII
_strdata = System.Text.Encoding.ASCII.GetString(_data)
Case EncodingType.Unicode
_strdata = System.Text.Encoding.Unicode.GetString(_data)
Case EncodingType.UTF7
_strdata = System.Text.Encoding.UTF7.GetString(_data)
Case EncodingType.UTF8
_strdata = System.Text.Encoding.UTF8.GetString(_data)
Case Else
Throw New BadEncodingException
End Select
' Set the message
_Message = _strdata
' Raise the AfterReceive event
RaiseEvent AfterReceive(Me, New EventArgs)
End Sub
 
Private Sub InitializeClient()
' Configure a UDPClient
Select Case Protocol
Case ProtocolType.Udp
If (_UDPClient Is Nothing) Then
_UDPClient = New UdpClient(ServerPort)
End If
Case Else
Throw New ProtocolNotSupportedException
End Select
End Sub
 
Private Sub InitializeThread()
' Start a worker thread
Try
_ThreadReceive = New Thread(AddressOf Receive)
_ThreadReceive.Start()
Catch ex As Exception
Throw ex
End Try
End Sub
 
Public Sub Start()
' Initialize the Client and the Thread
InitializeClient()
InitializeThread()
End Sub
 
Public Sub [Stop]()
' Close the UDPClient and stop the worker thread
Try
 
_closing = True
If Not (_UDPClient Is Nothing) Then
' Close the UDPClient and then force it to Nothing
_UDPClient.Close()
_UDPClient = Nothing
End If
_ThreadReceive.Abort()
 
Catch ex As Exception
Throw ex
End Try
End Sub
 
End Class
End Namespace


General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web01 | 2.5.120529.1 | Last Updated 8 Jun 2005
Article Copyright 2005 by tupacs01
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid