|
Multicast IP Summary
Multicast IP is an unusually useful, though often not well understood
feature of the IP networking protocols. In traditional IP, a host sends
packets to a single host (unicast transmission) or to all hosts (broadcast
transmission). IP Multicast offers a new possibility where a host can
send packets to a subset of all hosts as a "group transmission". This
is a bandwidth - conserving technology because the sender in an IP Multicast
group sends a single message, yet is is received by potentially thousands
of "subscribers" simultaneously.
IP Multicast revolves around the concept of a "group" - an arbitrary
group of receivers who have expressed an interest in receiving messages
on a particular data stream. Hosts wanting to subscribe to the group
do so via IGMP. For multicasting, Class D addresses must be used. All
IP Multicast group addresses fall in the range from 224.0.0.0 through
239.255.255.255, and addresses in the range 224.0.1.0 through 238.255.255.255
are referred to as globally scoped addresses. These are used to multicast
data between organizations and across the Internet.
If you are interested in studying the details of IP Multicast, you can
visit one of the standards archiving sites such as http://www.faqs.org/rfcs/rfc1112.html.
The Business Concept
In the enterprise where I currently work, we have a lot of SQL Servers
running SQL Agent batch jobs that basically get some data from the databases,
do stuff to it, (process it, send out notifications, other complex tasks)
and then quit. Then a specified time later, the batch job starts all
over. This is network resource and bandwidth intensive. My idea was that
if I can convince management to look at some alternative ways to handle
some of this traffic, we could be ahead of the game, since we do occasionally
get SQL timeouts. Obviously, judicious tuning of indexes and queries
can do a lot to help there, but I suspect that sometimes it's happening
just due to the sheer amount of "Stuff" going on.
My idea is to put together a Multicast IP messaging infrastructure.
This would have 3 main components:
1) a Master Service that continuously listens for "events" that arrive
in the form of live instances of various Message Classes that conform
to the IMessage interface. This service would then process these and
do the IP Multicast rebroadcast, and all listeners ("event subscribers")
that receive this and have in their configuration that they should respond
to the particular event will do so. The advantage here is that we only
need to send one control event message and the Master Service only needs
to send one Event Message broadcast. If you are subscribed, you get it,
and if it's the type you are supposed to respond to, you do so. Very
efficient, and works in real time. For example, if a corporate lead comes
into an FTP folder and the filesystemwatcher service sucks it up, it
will send an event control message to the Master Service, which will
in turn package it according to specific business rules and make an IP
multicast broadcast. Interested subscribers can act on this and even
send back a new message to the Master Service saying, in effect , "Hey
this is Pete! This one's mine! Thanks!". Master will dutifully record
that Pete is the guy that caught the pass, and on we go.
2) a Series of Event Listeners that can not only receive Multicast IP
Messages but can also respond with Messages of their own. This could
be something as simple as the prototype Multicast "Chat" app that I present
here as a proof - of - concept, or it could be something else.
3) A Library of Messages deriving from whatever IMessage
Interface eventually gets specified, each of which represents a different
action, different data, and different business rules. Listeners would
simply look at the MessageType and know what (if anything) they are supposed
to do with it.
Multicast IP Requirements In order for IP Multicasting to work, all routers in the communication
path must be multicast enabled. This should not be a problem, as almost
all current routers have this feature incorporated. The OS network interface
must also support IP Multicasting (almost all do) and of course, we already
have Multicast support in .NET.
How it works
Setting up a multicast listener / sender in .NET is extremely easy:
' Set up a new UdpClient instance
client = New UdpClient(localPort)
' Call the JoinMulticastGroup method, passing in the Group IP Address
and a Time To Live Integer
client.JoinMulticastGroup(groupAddress, ttl)
'Create a new endpoint on the specified port
remotEndPt = New IPEndPoint(groupAddress, remotePort)
The Time To Live Integer is important, because it tells the router(s)
how many router hops to keep multicasting on.
Each router decrements this by one as it handles the multicast packet
transmission. 32 is the maximum. To keep it "Local" you would probably
want to set this value in the app.config to "2".
Then we start a new Background thread on our Listener method, and start
the thread:
Dim thread As thread = New thread(AddressOf Me.Listener)
thread.IsBackground = True
thread.Start()
Our Listener Method:
Private Sub Listener()
done = False
Try
While Not done
Dim iPEndPoint As iPEndPoint = Nothing
Dim bs As Byte() = client.Receive(iPEndPoint)
Dim m As IMessage = PAB.Messaging.Util.RetrieveMessage(bs)
If m Is Nothing Then Return
message = m.MessageText
' need to use Invoke or BeginInvoke Syntax as message is on different thread--
Me.Invoke(New MethodInvoker(AddressOf ShowRecvdMessage))
End While
Catch e As Exception
MessageBox.Show(Me, e.Message + e.StackTrace, "Multicast Infrastructure
Error", MessageBoxButtons.OK, MessageBoxIcon.Hand)
End Try
End Sub
With our Listener set up, when a Message comes in, I'm calling a Shared
(static) Util method on my Util class:
Public Shared Function RetrieveMessage(ByVal bytMsg As Byte()) As IMessage
Dim m As IMessage
Dim strm As MemoryStream
strm = New MemoryStream(bytMsg)
Dim f As IFormatter
f = New Formatters.Binary.BinaryFormatter
Try
m = DirectCast(f.Deserialize(strm), IMessage)
Return m
Catch
Return Nothing
End Try
End Function
As you can see above, this receives the byte stream that
came into the Client, and deserializes it using the BinaryFormatter,
to return a live instance of type IMessage.My IMessage is a simple interface
that looks like so:
Namespace PAB.Messaging
Public Interface IMessage
Property MessageText() As String
Property MessageID() As System.Guid
Property MessageType() As String
Property MessageSender() As String
Property Payload() As Object
End Interface
End Namespace
IMessage has public properties to hold an ID (a Guid)
, message Text, a String representing the Message Type, a string to identity
the Message Sender, and finally an Object property to hold a payload.
We can use the Message Type to determine what we should do with this
when it is present.
The application I've put together here resembles (and
in fact, it actually is) a "chat" type of application where
each client is able to both send and receive. I've hooked in the
Message Class infrastructure into it to fill it out with more robust
capability in anticipation of delivering the next phase for Part II of
this series which will be the Master Service as described above.
You can download the VB.NET Solution for the App at the
link below. If you want to run two instances of this on the same machine
to try it out, you'll need to remember to change one of either the LocalPort
or RemotePort app.Config settings to another port number, and then reverse
the LocalPort and RemotePort settings on the other instance of the app
so you don't get any socket errors (you can only make one socket
connection to one port on the same machine at a time).
Conclusion
As .NET developers and architects, it's extremely important
that we try to "stretch" the paradigm in our Enterprise and
look at new ways to "think outside the box". IP Multicast has
the potential to do much more than just stream video and handle Chat
traffic. It can be used to implement a robust, real-time messaging and
control infrastructure that is both bandwidth conservative and reliable.
Download the Source Code that accompanies this article |