< C++ Multicast Program Example (Cont...) | Main | VB .NET Multicast Program Example >

 


 

Chapter 8 Part 25:

Client (and Server) Sockets Communication

 

 

What do we have in this chapter 8 Part 25?

  1. C# Multicast Program Example

 

 

C# Multicast Program Example

 

Create a new console application project and you might use MulticastCS as the name.

 

C# Multicast Program Example - a new project creation of the console application type in Visual Studio 2008

 

 

Add/edit the following using directives at the top of the file.

 

using System;

using System.Collections;

using System.Net;

using System.Net.Sockets;

 

Next, rename the class to MulticastEndpoint.

 

C# Multicast Program Example - renaming the class

 

Add the following code for the MulticastEndpoint class.

 

class MulticastEndpoint

{

    public ArrayList        localInterfaceList, multicastJoinList;

    public Socket           mcastSocket;

    public IPAddress        bindAddress;

    public int              bufferSize;

    public int              localPort;   

    public byte [ ]          dataBuffer;

 

    /// <summary>

    /// Simple constructor for the

    /// </summary>

    public MulticastEndpoint()

    {

        localInterfaceList = new ArrayList();

        multicastJoinList = new ArrayList();

        bufferSize = 512;

        mcastSocket = null;

    }

 

    /// <summary>

    /// This method creates the socket, joins it to the given multicast groups, and initializes

    /// the send/receive buffer. Note that the local bind address should be the wildcard address

    /// because it is possible to join multicast groups on one or more local interface and if

    /// a socket is bound to an explicit local interface, it can lead to user confusion (although

    /// this does currently work on Windows OSes).

    /// </summary>

    /// <param name="port">Local port to bind socket to</param>

    /// <param name="bufferLength">Length of the send/recv buffer to create</param>

    public void Create(int port, int bufferLength)

    {

        localPort = port;

 

        Console.WriteLine("Creating socket, joining multicast group and");

        Console.WriteLine("     initializing the send/receive buffer");

        try

        {

            // If no bind address was specified, pick an appropriate one based on the multicast

            // group being joined.

            if ( bindAddress == null )

            {

                IPAddress tmpAddr = (IPAddress) multicastJoinList[0];

 

                if ( tmpAddr.AddressFamily == AddressFamily.InterNetwork )

                    bindAddress = IPAddress.Any;

                else if ( tmpAddr.AddressFamily == AddressFamily.InterNetworkV6 )

                    bindAddress = IPAddress.IPv6Any;

            }

 

            // Create the UDP socket

            Console.WriteLine("Creating the UDP socket...");

            mcastSocket = new Socket(

                bindAddress.AddressFamily,

                SocketType.Dgram,

                0

                );

 

            Console.WriteLine("{0} multicast socket created", bindAddress.AddressFamily.ToString());

 

            // Bind the socket to the local endpoint

            Console.WriteLine("Binding the socket to the local endpoint...");

            IPEndPoint  bindEndPoint = new IPEndPoint( bindAddress, port );

            mcastSocket.Bind( bindEndPoint );

            Console.WriteLine("Multicast socket bound to: {0}", bindEndPoint.ToString());

 

            // Join the multicast group

            Console.WriteLine("Joining the multicast group...");

            for(int i = 0; i < multicastJoinList.Count ;i++)

            {

                for(int j = 0; j < localInterfaceList.Count ;j++)

                {

                    // Create the MulticastOption structure which is required to join the

                    //    multicast group

                    if ( mcastSocket.AddressFamily == AddressFamily.InterNetwork )

                    {

                        MulticastOption     mcastOption = new MulticastOption(

                            (IPAddress) multicastJoinList[i],

                            (IPAddress) localInterfaceList[j]

                            );

 

                        mcastSocket.SetSocketOption(

                            SocketOptionLevel.IP,

                            SocketOptionName.AddMembership,

                            mcastOption

                            );

                    }

                    else if ( mcastSocket.AddressFamily == AddressFamily.InterNetworkV6 )

                    {

                        IPv6MulticastOption ipv6McastOption = new IPv6MulticastOption(

                            (IPAddress) multicastJoinList[i],

                            ( (IPAddress) localInterfaceList[j] ).ScopeId

                            );

 

                        mcastSocket.SetSocketOption(

                            SocketOptionLevel.IPv6,

                            SocketOptionName.AddMembership,

                            ipv6McastOption

                            );

                    }

 

                    Console.WriteLine("Joined multicast group {0} on interface {1}",

                        multicastJoinList[i].ToString(),

                        localInterfaceList[j].ToString()

                        );

                }

            }

 

            // Allocate the send and receive buffer

            Console.WriteLine("Allocating the send and receive buffer...");

            dataBuffer = new byte [ bufferLength ];

        }

        catch ( SocketException err )

        {

            Console.WriteLine("Exception occurred when creating multicast socket: {0}", err.Message);

            throw;

        }

    }

 

    /// <summary>

    /// This method drops membership to any joined groups. To do so, you have to

    /// drop the group exactly as you joined it -- that is the local interface

    /// and multicast group must be the same as when it was joined. Also note

    /// that it is not required to drop joined groups before closing a socket.

    /// When a socket is closed all multicast joins are dropped for you -- this

    /// routine just illustrates how to drop a group if you need to in the middle

    /// of the lifetime of a socket.

    /// </summary>

    public void LeaveGroups()

    {

        try

        {

            Console.WriteLine("Dropping membership to any joined groups...");

            for(int i = 0; i < multicastJoinList.Count ;i++)

            {

                for(int j = 0; j < localInterfaceList.Count ;j++)

                {

                    // Create the MulticastOption structure which is required to drop the

                    //    multicast group (the same structure used to join the group is

                    //    required to drop it).

                    if ( mcastSocket.AddressFamily == AddressFamily.InterNetwork )

                    {

                        MulticastOption     mcastOption = new MulticastOption(

                            (IPAddress) multicastJoinList[i],

                            (IPAddress) localInterfaceList[j]

                            );

 

                        mcastSocket.SetSocketOption(

                            SocketOptionLevel.IP,

                            SocketOptionName.DropMembership,

                            mcastOption

                            );

                    }

                    else if ( mcastSocket.AddressFamily == AddressFamily.InterNetworkV6 )

                    {

                        IPv6MulticastOption ipv6McastOption = new IPv6MulticastOption(

                            (IPAddress) multicastJoinList[i],

                            ( (IPAddress) localInterfaceList[j] ).ScopeId

                            );

 

                        mcastSocket.SetSocketOption(

                            SocketOptionLevel.IPv6,

                            SocketOptionName.DropMembership,

                            ipv6McastOption

                            );

                    }

 

                    Console.WriteLine("Dropping multicast group {0} on interface {1}",

                        multicastJoinList[i].ToString(),

                        localInterfaceList[j].ToString()

                        );

                }

            }

        }

        catch

        {

            Console.WriteLine("LeaveGroups: No multicast groups joined");

        }

    }

 

    /// <summary>

    /// This method sets the outgoing interface when a socket sends data to a multicast

    /// group. Because multicast addresses are not routable, the network stack simply

    /// picks the first interface in the routing table with a multicast route. In order

    /// to change this behavior, the MulticastInterface option can be used to set the

    /// local interface on which all outgoing multicast traffic is to be sent (for this

    /// socket only). This is done by converting the 4 byte IPv4 address (or 16 byte

    /// IPv6 address) into a byte array.

    /// </summary>

    /// <param name="sendInterface"></param>

    public void SetSendInterface( IPAddress sendInterface )

    {

        // Set the outgoing multicast interface

        try

        {

            Console.WriteLine("Setting the outgoing multicast interface...");

            if ( mcastSocket.AddressFamily == AddressFamily.InterNetwork )

            {

                mcastSocket.SetSocketOption(

                    SocketOptionLevel.IP,

                    SocketOptionName.MulticastInterface,

                    sendInterface.GetAddressBytes()

                    );

             }

            else

            {

                byte [ ] interfaceArray = BitConverter.GetBytes( (int)sendInterface.ScopeId );

 

                mcastSocket.SetSocketOption(

                    SocketOptionLevel.IPv6,

                    SocketOptionName.MulticastInterface,

                    interfaceArray

                    );

            }

            Console.WriteLine("Setting multicast send interface to: " + sendInterface.ToString());

        }

        catch ( SocketException err )

        {

            Console.WriteLine("SetSendInterface: Unable to set the multicast interface: {0}", err.Message);

            throw;

        }

    }    

 

    /// <summary>

    /// This method takes a string and repeatedly copies it into the send buffer

    /// to the length of the send buffer.

    /// </summary>

    /// <param name="message">String to copy into send buffer</param>

    public void FormatBuffer( string message )

    {

        byte [ ]  byteMessage = System.Text.Encoding.ASCII.GetBytes( message );

        int         index = 0;

 

        // First convert the string to bytes and then copy into send buffer

        Console.WriteLine("Formatting the send buffer...");

        while ( index < dataBuffer.Length )

        {

            for(int j=0; j < byteMessage.Length ;j++)

            {

                dataBuffer[ index ] = byteMessage[ j ];

                index++;

 

                // Make sure we don't go past the send buffer length

                if ( index >= dataBuffer.Length )

                {

                    break;

                }

            }

        }

    }

    }

 

 

 

Next, add another class and name it MulticastSample. The Main() is in this class.

 

class MulticastSample

    {

        /// <summary>

        /// This method prints usage information for multicast sample

        /// </summary>

        static void usage()

        {

            Console.WriteLine("Executable_file_name [/i ip] [/b ip] [/m ip] [/p port] [/x num] [/t text]");

            Console.WriteLine("              [/n count] [/s | /r]");

            Console.WriteLine("Available options:");

            Console.WriteLine("   /i ip                Local interface to join multicast group(s) on");

            Console.WriteLine("   /b ip               Local IP to bind the socket to");

            Console.WriteLine("   /m ip              Multicast group to join");

            Console.WriteLine("   /p port           Port to listen on or send to");

            Console.WriteLine("   /x size           Length of send or receive buffer");

            Console.WriteLine("   /t text Text message to put in send buffer");

            Console.WriteLine("   /n count  Number of times to send or receive");

            Console.WriteLine("   /s        Send data to a multicast group");

            Console.WriteLine("   /r                    Receive data send to the group");

            Console.WriteLine();

        }

 

        /// <summary>

        /// This is the main routine which parses the command line and creates the

        /// multicast socket as given by the command line parameters. The sample

        /// can either be invoked as a multicast sender or receiver.

        ///

        /// To invoke as a multicast receiver:

        ///     multicast.exe /r /i 10.10.10.1 /m 234.6.6.6

        /// To invoke as a multicast sender:

        ///     multicast.exe /s /i 10.10.10.99 /m 234.6.6.6

        /// </summary>

        /// <param name="appArguments">Command line arguments</param>

        static void Main(string[] appArguments)

        {

            MulticastEndpoint mcastEndpoint = new MulticastEndpoint();

            string textMessage = "Hello Bastard World";

            int port = 0, bufferLength = 1024, opCount = 10;

            bool isSender = true;

 

            // Parse the command line

            for (int i = 0; i < appArguments.Length; i++)

            {

                try

                {

                    if ((appArguments[i][0] == '-') || (appArguments[i][0] == '/'))

                    {

                        switch (Char.ToLower(appArguments[i][1]))

                        {

                            case 'b':

                                // Address to bind multicast socket to

                                mcastEndpoint.bindAddress = IPAddress.Parse(appArguments[++i]);

                                break;

                            case 'c':

                                // How many times to send or receive

                                opCount = System.Convert.ToInt32(appArguments[++i].ToString());

                                break;

                            case 'i':

                                // Local interface to join group(s) on

                                mcastEndpoint.localInterfaceList.Add(IPAddress.Parse(appArguments[++i]));

                                break;

                            case 'm':

                                // Multicast group to join

                                mcastEndpoint.multicastJoinList.Add(IPAddress.Parse(appArguments[++i]));

                                break;

                            case 'p':

                                // Port number to bind to or send to

                                port = System.Convert.ToInt32(appArguments[++i].ToString());

                                break;

                            case 'r':

                                // Application invoked as receiver

                                isSender = false;

                                break;

                            case 's':

                                // Application invoked as sender

                                isSender = true;

                                break;

                            case 't':

                                // Text message to send

                                textMessage = appArguments[++i];

                                break;

                            case 'x':

                                // Length of send/receive buffer

                                bufferLength = System.Convert.ToInt32(appArguments[++i].ToString());

                                break;

                            default:

                                usage();

                                return;

                        }

                    }

                }

                catch

                {

                    usage();

                    return;

                }

            }

 

            // Make sure user specified at least on multicast group and interface to join

            if ((mcastEndpoint.multicastJoinList.Count == 0) || (mcastEndpoint.localInterfaceList.Count == 0))

            {

                Console.WriteLine("Please specify a multicast group and interface to join on!");

                usage();

                return;

            }

 

            // Now, create the multicast socket

            Console.WriteLine("Creating the multicast socket...");

            try

            {

                if (isSender == true)

                {

                    // For the sender, we don't care what the local port the socket is bound to

                    mcastEndpoint.Create(

                        0,               // If the sender we don't care what local port we bind to

                        bufferLength

                        );

                }

                else

                {

                    mcastEndpoint.Create(port, bufferLength);

                }

 

                if (isSender == true)

                {

                    IPEndPoint destinationGroup = new IPEndPoint((IPAddress)mcastEndpoint.multicastJoinList[0], port);

                    int rc;

 

                    // Set the send interface for all outgoing multicast packets

                    Console.WriteLine("Setting the send interface for all outgoing multicast packets...");

                    mcastEndpoint.SetSendInterface((IPAddress)mcastEndpoint.localInterfaceList[0]);

                    mcastEndpoint.FormatBuffer(textMessage);

 

                    // Send the message the requested number of times

                    Console.WriteLine("Sending the message the requested number of times...");

                    for (int i = 0; i < opCount; i++)

                    {

                        try

                        {

                            rc = mcastEndpoint.mcastSocket.SendTo(mcastEndpoint.dataBuffer, destinationGroup);

                            Console.WriteLine("Multicast SendTo() is OK...");

                            Console.WriteLine("Sent {0} bytes to {1}", rc, destinationGroup.ToString());

                        }

                        catch (SocketException err)

                        {

                            Console.WriteLine("Multiast SendTo() failed: " + err.Message);

                        }

                    }

                }

                else

                {

                    IPEndPoint senderEndPoint = new IPEndPoint((IPAddress)mcastEndpoint.localInterfaceList[0], 0);

                    EndPoint castSenderEndPoint = (EndPoint)senderEndPoint;

                    int rc;

 

                    for (int i = 0; i < opCount; i++)

                    {

                        try

                        {

                            rc = mcastEndpoint.mcastSocket.ReceiveFrom(mcastEndpoint.dataBuffer, ref castSenderEndPoint);

                            Console.WriteLine("Multicast ReceiveFrom() is OK...");

                            senderEndPoint = (IPEndPoint)castSenderEndPoint;

                            Console.WriteLine("Received {0} bytes from {1}: '{2}'",

                                rc,

                                senderEndPoint.ToString(),

                                System.Text.Encoding.ASCII.GetString(mcastEndpoint.dataBuffer, 0, rc)

                                );

                        }

                        catch (SocketException err)

                        {

                            Console.WriteLine("Multicast ReceiveFrom() failed: " + err.Message);

                        }

                    }

                }

 

                // Drop membership to groups. This isn't required in this sample as closing the socket

                //    will implicitly leave all groups joined, but it's a good practice.

                mcastEndpoint.LeaveGroups();

            }

            catch

            {

                Console.WriteLine("An error occurred creating the multicast socket");

            }

            finally

            {

                if (mcastEndpoint.mcastSocket != null)

                {

                    Console.WriteLine("Closing the multicast socket...");

                    mcastEndpoint.mcastSocket.Close();

                }

                mcastEndpoint = null;

            }

        }

    }

 

Build the project and make sure there is no error.

 

C# Multicast Program Example - building the project

 

Run the project. Any error will be thrown by the exception handlers.

 

C# Multicast Program Example - running the project  

 

The following is the sample output.

 

C# Multicast Program Example - a sample output without arguments supplied

 

The following are sample outputs for sender and receiver when run from the command prompt. This program example was tested on a simple private network with two computers connected using the peer-to-peer cable (cross cable). You may want to test on the real network with more receivers that will resemble the chat system. Firstly, we run the receiver.

 

C# Multicast Program Example - a sample output that acts as receiver

 

Then, we run the sender.

 

C# Multicast Program Example - a sample output that acts as a sender, sending some data

 

The following is the receiver output screenshot when the communication was completed.

 

C# Multicast Program Example - a sample of the receiver screen when the communication was completed

 

 

 


 

< C++ Multicast Program Example (Cont...) | Main | VB .NET Multicast Program Example >