Posted by VelMurugan
- Dec 14, 2008, 04:50 AM
The trouble with the UDPClient class in .NET
Microsoft, in its infinite wisdom, built this class in .NET as a simplified method for UDP communication. The one critical thing they forgot to include was a simple time-out feature.
What's wrong with not having a time-out? Plenty, if you have one end of the transmission expecting to receive data, and the source of the transmission decided to go belly-up. If you use the UDPClient.Receive method, and the application sending the message does not send the message, then that UDPClient.Receive method will block forever--at least until the application is closed by the user.
A rather nasty way of handling such a situation. By the very nature of UDP, packets can get lost and never be received, causing the application to wait forever, or a bug in the sending application may simply cause it to never send the message that is expected.
Why on earth Microsoft did not put a time-out feature in this class is beyond me. What this means is that if you are doing any real programming you'll find the UDPClient class to be hopelessly inadequate. You'll have to instead use the more generic Socket Class to accomplish your task.
Below is a code sample that uses the Socket Class to accomplish the tasks that the UDPClient is meant to do, but with a timeout.
The UDPClient Class is for synchronized data transmission. If you are trying to do asynchronized transmission, you would have had to use the Socket class, anyhow.
Imports System.Net.Sockets
Protected Shared Function UDPDataTransmit( _
ByVal sBuff() As Byte, ByRef rBuff() As Byte, _
ByVal IP As String, ByVal Port As Integer) As Integer 'Returns # bytes received
Dim retstat As Integer
Dim Sck As Sockets.Socket
Dim Due As DateTime
Dim Encrp As IPEndPoint
Try
Sck = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)
Sck.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 10000)
Sck.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 10000)
Encrp = New IPEndPoint(IPAddress.Parse(IP), Port)
retstat = Sck.SendTo(sBuff, 0, sBuff.Length, SocketFlags.None, Encrp)
If retstat > 0 Then
Due = Now.AddMilliseconds(10000) '10 second time-out
Do While Sck.Available = 0 AndAlso Now < Due
Loop
If Sck.Available = 0 Then
'timed-out
retstat = -3
Return retstat
End If
ReDim rBuff(Sck.Available - 1)
retstat = Sck.ReceiveFrom(rBuff, 0, Sck.Available, SocketFlags.None, CType(Encrp, EndPoint))
Else
retstat = -1 ' fail on send
End If
Catch ex As Exception
'General Exception received--add code here to analyze the exception. A messagebox would be one idea.
retstat = -2
Finally
Sck.Close() 'Always close the socket when done.
End Try
Return retstat
End Function
Source : VBCity