Public Class UDPCommon
Implements IDisposable
'The UDP listening components.
Private WithEvents locUDP As System.Net.Sockets.Socket
Private WithEvents locUDPOut As System.Net.Sockets.UdpClient
Private ThreadListen As New Threading.Thread(AddressOf WaitForPending)
Private timeCount As Integer
Private broad As System.Net.IPEndPoint
'The dataQueue
Private dgList As Queue(Of DataGramReceiver)
'The result
Private disposedValue As Boolean = False ' To detect redundant calls
'Synchronization.
Private Shared myContext As System.Threading.SynchronizationContext
#Region "Constructors and Destructors"
Public Sub New()
'Set up the queue.
dgList = New Queue(Of DataGramReceiver)
locUDPOut = New Net.Sockets.UdpClient(11013)
locUDP = New Net.Sockets.Socket(Net.Sockets.AddressFamily.InterNetwork, Net.Sockets.SocketType.Dgram, Net.Sockets.ProtocolType.Udp)
locUDP.SetSocketOption(Net.Sockets.SocketOptionLevel.Socket, Net.Sockets.SocketOptionName.ReuseAddress, True)
locUDP.Bind((New Net.IPEndPoint(Net.IPAddress.Any, 11013)))
locUDPOut.EnableBroadcast = True
broad = New System.Net.IPEndPoint(System.Net.IPAddress.Broadcast, 11013)
myContext = System.Threading.SynchronizationContext.Current
'Start listening.
ThreadListen.Name = "Listening Thread"
ThreadListen.Start()
End Sub
' IDisposable
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
ThreadListen.Abort()
locUDP.Close()
locUDPOut.Close()
End If
' TODO: free shared unmanaged resources
End If
Me.disposedValue = True
End Sub
#Region " IDisposable Support "
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
#End Region
#Region "Properties and Events"
Public Event MessageIn()
Public ReadOnly Property MessageCount() As Integer
Get
Return dgList.Count
End Get
End Property
Public ReadOnly Property NextMessage() As DataGramReceiver
Get
Return dgList.Dequeue
End Get
End Property
#End Region
#Region "Public Functions"
'This will get the next DGR from the queue.
Public Function GetNext() As DataGramReceiver
Dim dgRet As New DataGramReceiver
Threading.Monitor.Enter(Me)
Try
If dgList.Count > 0 Then
dgRet = New DataGramReceiver(dgList.Dequeue)
End If
Catch ex As Exception
Windows.Forms.MessageBox.Show(ex.Message, "Error Getting DataGramReceiver", MessageBoxButtons.OK, MessageBoxIcon.Error)
Finally
Threading.Monitor.Exit(Me)
End Try
'It may be the default, or it may not, either way it is a good local copy in the calling thread, return it.
Return dgRet
End Function
'Empties the queue
Public Sub Flush()
Threading.Monitor.Enter(Me)
Try
dgList.Clear()
Finally
Threading.Monitor.Exit(Me)
End Try
End Sub
Public Sub SendMessage(ByVal btArr() As Byte, ByVal toWho As Byte, ByVal what As Byte)
Dim lBtArr(btArr.Length + 2) As Byte
lBtArr(0) = 100 'This is the OL ID.
lBtArr(1) = toWho
lBtArr(2) = what
System.Array.Copy(btArr, 0, lBtArr, 3, btArr.Length)
'NOTE: NEED TO CHECK THAT THIS IS DOING AS IT SHOULD.
locUDP.SendTo(lBtArr, lBtArr.Length, Net.Sockets.SocketFlags.Broadcast, broad)
End Sub
#End Region
#Region "Private Functions"
Private Sub WaitForPending()
Dim bHolder(511) As Byte
Dim numIn As Integer
Dim dgRec As DataGramReceiver
Dim bTrans() As Byte
While True
If CBool(locUDP.Available) Then
numIn = locUDP.Receive(bHolder, 512, Net.Sockets.SocketFlags.None)
If numIn > 4 Then
If bHolder(1) = 0 OrElse bHolder(1) = 100 Then
'Set the holder up to the right size.
ReDim bTrans(numIn)
Array.Copy(bHolder, 3, bTrans, 0, numIn - 3)
dgRec = New DataGramReceiver(128, bHolder(2), bTrans)
Add(dgRec)
End If
End If
End If
End While
End Sub
'Adds one DGR to the queue
Private Sub Add(ByVal dgR As DataGramReceiver)
'Set the monitor.
Threading.Monitor.Enter(Me)
Try
dgList.Enqueue(dgR) 'That's all that happens.
Finally
Threading.Monitor.Exit(Me)
End Try
myContext.Post(AddressOf GotData, Nothing)
End Sub
'This is invoked by the other thread.
Private Sub GotData(ByVal state As Object)
RaiseEvent MessageIn()
End Sub
#End Region
End Class