Sample Multicast Application



Sample Multicast Application

Multicast applications come in handy when a device needs to send information to multiple remote devices without having to maintain a connection to each device or send out multiple packets (one for each device). This section demonstrates a simple multicast whiteboard/chat system, in which any client that joins the multicast group can forward messages to all devices in the multicast group and can receive messages from all the other devices in the group. This is a common application for multicast communication. By allowing anyone on the network to join the multicast group chat, you create an environment where everyone can post comments to the group and see the posts from everyone else.

The basic format for this program will be the TcpChat program (Listing 9.7) introduced in Chapter 9. Instead of sending packets to an individual device, the chat program sends packets to the 224.100.0.1 multicast IP address. Any clients listening to that multicast group will receive the messages. Similarly, the TcpChat program will be modified to listen to the same multicast group address and display messages received from other chat clients on the network.

The easiest way to modify the existing TcpChat program is to create a new Thread object, which monitors the multicast group address. As messages are received on the address, they are displayed in the list box. The message-sending function can remain the same, with the exception that the multicast group IP address must now be used. Listing 10.13 is the multicast chat program that uses this concept.

Listing 10.13: The MulticastChat.cs program
Start example
using System;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
class MulticastChat    Form
{
  TextBox newText;
  ListBox results;
  Socket sock;
  Thread receiver;
  IPEndPoint multiep = new IPEndPoint(IPAddress.Parse("224.100.0.1"), 9050);
  public MulticastChat()
  {
   Text = "Multicast Chat Program";
   Size = new Size(400, 380);
   Label label1 = new Label();
   label1.Parent = this;
   label1.Text = "Enter text string:";
   label1.AutoSize = true;
   label1.Location = new Point(10, 30);
   newText = new TextBox();
   newText.Parent = this;
   newText.Size = new Size(200, 2 * Font.Height);
   newText.Location = new Point(10, 55);
   results = new ListBox();
   results.Parent = this;
   results.Location = new Point(10, 85);
   results.Size = new Size(360, 18 * Font.Height);
   Button sendit = new Button();
   sendit.Parent = this;
   sendit.Text = "Send";
   sendit.Location = new Point(220,52);
   sendit.Size = new Size(5 * Font.Height, 2 * Font.Height);
   sendit.Click += new EventHandler(ButtonSendOnClick);
   Button closeit = new Button();
   closeit.Parent = this;
   closeit.Text = "Close";
   closeit.Location = new Point(290, 52);
   closeit.Size = new Size(5 * Font.Height, 2 * Font.Height);
   closeit.Click += new EventHandler(ButtonCloseOnClick);
   sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
            ProtocolType.Udp);
   IPEndPoint iep = new IPEndPoint(IPAddress.Any, 9050);
   sock.Bind(iep);
   sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership,
              new MulticastOption(IPAddress.Parse("224.100.0.1")));
   receiver = new Thread(new ThreadStart(packetReceive));
   receiver.IsBackground = true;
   receiver.Start();
  }
  void ButtonSendOnClick(object obj, EventArgs ea)
  {
   byte[] message = Encoding.ASCII.GetBytes(newText.Text);
   newText.Clear();
   sock.SendTo(message, SocketFlags.None, multiep);
  }
  void ButtonCloseOnClick(object obj, EventArgs ea)
  {
   receiver.Abort();
   sock.Close();
   Close();
  }
  void packetReceive()
  {
   EndPoint ep = (EndPoint)multiep;
   byte[] data = new byte[1024];
   string stringData;
   int recv;
   while (true)
   {
     recv = sock.ReceiveFrom(data, ref ep);
     stringData = Encoding.ASCII.GetString(data, 0, recv);
     results.Items.Add("from " + ep.ToString() + ": " + stringData);
   }
  }
  public static void Main()
  {
   Application.Run(new MulticastChat());
  }
}
End example

The MulticastChat program is not unlike the other chat programs presented in this book. The main difference is that it creates a Socket object to receive and send data out the 224.100.0.1 multicast group address:

sock = new Socket(AddressFamily.InterNetwork,
     SocketType.Dgram, ProtocolType.Udp);
IPEndPoint iep = new IPEndPoint(IPAddress.Any, 9050);
sock.Bind(iep);
sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership,
   new MulticastOption(IPAddress.Parse("224.100.0.1")));

Because the socket joins the multicast group using the SetSocketOption() method, it must use the Bind() method to bind it to a specific port. For the sake of simplicity, it is bound to the same port that the multicast group uses.

A Thread object is then created to listen for messages on the multicast group address using the packetReceive() method. The packetReceive() method enters a continuous loop, waiting for messages from the multicast group and displaying them in the results ListBox object:

void packetReceive()
{
  EndPoint ep = (EndPoint)multiep;
  byte[] data = new byte[1024];
  string stringData;
  int recv;
  while (true)
  {
   recv = sock.ReceiveFrom(data, ref ep);
   stringData = Encoding.ASCII.GetString(data, 0, recv);
   results.Items.Add("from " + ep.ToString() + ": " + stringData);
  }
}

Because the multicast chat program is a connectionless application, you must tell it when to stop and close the socket. When the Close button is clicked, the receiver thread is terminated, the created socket is properly closed on the system, and the window form is closed:

void ButtonCloseOnClick(object obj, EventArgs ea)
{
  receiver.Abort();
  sock.Close();
  Close();
}

Testing the Multicast Chat Program

Because it is a Windows forms program, when you compile MulticastChat.cm, you will most likely want to use the /t compiler option to make it a Windows executable:

csc /t:winexe MulticastChat.cs

After the compile finishes, you can run the program by either double-clicking the program name in the Windows Explorer window, or running it from a command prompt window.

Warning 

Because the MulticastChat program binds to a specific UDP port, only one instance can be run on a machine.

When the program starts, the chat window should be displayed, and it should be ready to accept messages from the multicast group. To check this out, you can first see if the UDP port appears in the netstat output:

C:\>netstat -a
Active Connections
Proto Local Address     Foreign Address    State
.
.
UDP  abednego:9050     *:*
.
.
C:\>

Sure enough, the system has created a socket on UDP port 9050. You can also use WinDump or Analyzer to monitor the network traffic generated by the MulticastChat program. You should see the standard IGMP packets sent out when the program starts:

C:\>windump igmp
windump: listening on\Device\Packet_El90x1
07:24:09.950210 192.168.1.6 > 224.100.0.1: 192.168.1.6 > 224.100.0.1: igmp v2
report 224.100.0.1 [ttl 1]
07:24:14.799582 192.168.1.6 > 224.100.0.1: 192.168.1.6 > 224.100.0.1: igmp v2
report 224.100.0.1 [ttl 1]
1237 packets received by filter
0 packets dropped by kernel
C:\>

After starting the program, you can enter a text message in the text box and click the Send button. Because the application itself is listening to the multicast group address, the message will appear in the list box. If you have a network with multiple Windows devices, you can experiment by running the application on multiple devices at the same time. Each instance of the application should display the message sent by another other device on the subnet.

Note 

Remember that if your network uses routers, they must be configured to allow multicast traffic to be forwarded for this program to work across subnets.

 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows