< C# Raw Socket Ping Program Example (Cont...) | Main | .NET IP Multicasting & C++ Example >

 


 

Chapter 8 Part 22:

Client (and Server) Sockets Communication

 

 

What do we have in this chapter 8 Part 22?

  1. C++ Raw Socket IGMP Program Example

  2. C# Raw Socket IGMP Program Example

 

 

C++ Raw Socket IGMP Program Example

 

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

 

C++ Raw Socket IGMP Program Example - creating a new CLR console application project in VS 2008

 

 

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

 

using namespace System;

using namespace System::Net;

using namespace System::Net::Sockets;

using namespace System::Collections;

// Reference the protocol header classes

using namespace ProtocolHeaderDefinitionCP;

 

C++ Raw Socket IGMP Program Example - invoking the References page

 

C++ Raw Socket IGMP Program Example - the project's property page, adding a new reference

 

 

C++ Raw Socket IGMP Program Example - browsing and finding the sahred DLL file

 

C++ Raw Socket IGMP Program Example - selecting the DLL file that contains the protocol header definitions

 

C++ Raw Socket IGMP Program Example - the included DLL file can be seen in the References: field under the Name column

 

Build the project to see the included reference to the DLL is working and accessible.

 

C++ Raw Socket IGMP Program Example - building the project

 

C++ Raw Socket IGMP Program Example - the build messages that can be seen in the VS 2008 Output window

 

Add the following usage() function.

 

static void usage()

{

    Console::WriteLine("Executable_file_name [-c send-count] [-g x.y.z.w] [-i a.b.c.d] [-p pad]");

    Console::WriteLine("Available options:");

    Console::WriteLine("    -g x.y.z.w       - Multicast group to send query for");

    Console::WriteLine("    -i a.b.c.d       - Local interface to send query on");

    Console::WriteLine("    -p pad-bytes     - Number of pad bytes at end of packet");

    Console::WriteLine("    -c send-count    - Number of times to send query");

    Console::WriteLine();

}

 

Next, add the main() code.

 

int main(array<System::String ^> ^args)

{

    IPAddress^ groupAddress = IPAddress::Parse("234.6.7.8");

    IPAddress^ localAddress = IPAddress::Any;

    int padByteCount = 0, sendCount = 5;

 

    // Parse the command line

    if(args->Length)

    {

    for (int i = 0; i < args->Length; i++)

    {

        try

        {

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

            {

                switch (Char::ToLower(args[i][1]))

                {

                    case 'c':

                        // Number of times to send packet

                        sendCount = Convert::ToInt32(args[++i]->ToString());

                        break;

                    case 'g':

                        // Multicast group

                        groupAddress = IPAddress::Parse(args[++i]->ToString());

                        break;

                    case 'i':

                        // Local interface to send query from

                        localAddress = IPAddress::Parse(args[++i]->ToString());

                        break;

                    case 'p':

                        // Amount of pad data

                        padByteCount = Convert::ToInt32(args[++i]->ToString());

                        break;

                    default:

                        usage();

                        return 0;

                }

            }

        }

        catch(Exception^ err)

        {

            Console::WriteLine("Error: " + err->Message);

            usage();

            return 0;

        }

    }

}

else

{

   usage();

   return 0;

}

 

    // Display the parameter

    Console::WriteLine("Sending query for group: {0}", groupAddress->ToString());

    Console::WriteLine("Sending on interface   : {0}", localAddress->ToString());

    Console::WriteLine("Number of pad bytes    : {0}", padByteCount);

    Console::WriteLine("Send count             : {0}", sendCount);

 

    IgmpHeader^ igmpHeader = gcnew IgmpHeader();

    Ipv4Header^ ipv4Header = gcnew Ipv4Header();

    ArrayList^ headerList = gcnew ArrayList();

    IPEndPoint^ igmpDestination = gcnew IPEndPoint(IgmpHeader::AllSystemsAddress, 0);

    IPEndPoint^ localEndpoint = gcnew IPEndPoint(localAddress, 0);

    Socket^ igmpSocket;

    array<Byte>^ igmpPacket;

    array<Byte>^ padBytes;

 

    // Build the IPv4 header

    Console::WriteLine("Building the IPv4 header...");

    ipv4Header->Version = 4;

    ipv4Header->Protocol = (Byte)ProtocolType::Igmp;

    ipv4Header->Ttl = 1;

    ipv4Header->Offset = 0;

    ipv4Header->Length = 20;

    ipv4Header->TotalLength = (unsigned short)Convert::ToUInt16(IgmpHeader::IgmpHeaderLength + padByteCount);

    ipv4Header->SourceAddress = localAddress;

    ipv4Header->DestinationAddress = IgmpHeader::AllSystemsAddress;

 

    // Add the header to the list of headers

    Console::WriteLine("Adding the header to the list of headers...");

    headerList->Add(ipv4Header);

 

    // Build the IGMP header

    igmpHeader->VersionType = IgmpHeader::IgmpMembershipQuery;

    igmpHeader->MaximumResponseTime = 100;

    igmpHeader->GroupAddress = groupAddress;

 

    // Allocate pad bytes as necessary

    Console::WriteLine("Allocating pad bytes as necessary...");

    padBytes = gcnew array<Byte>(padByteCount);

 

    // Add the IGMP header to the list of headers

    Console::WriteLine("Adding the IGMP header to the list of headers...");

    headerList->Add(igmpHeader);

 

    // Build the packet

    Console::WriteLine("Building the packet...");

    igmpPacket = igmpHeader->BuildPacket(headerList, padBytes);

 

    // Create the raw socket

    Console::WriteLine("Creating the raw socket, Socket()...");

    igmpSocket = gcnew Socket(

                        groupAddress->AddressFamily,

                        SocketType::Raw,

                        ProtocolType::Igmp

        );

 

    // Bind to a local interface

    Console::WriteLine("Binding to a local interface, Bind()...");

    igmpSocket->Bind(localEndpoint);

 

    // Set the HeaderIncluded option

    Console::WriteLine("Setting the HeaderIncluded option...");

    igmpSocket->SetSocketOption(SocketOptionLevel::IP, SocketOptionName::HeaderIncluded, 1);

 

    // Send the packet the requested number of times

    Console::WriteLine("Send the packet the requested number of times...");

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

    {

        int rc = igmpSocket->SendTo(igmpPacket, igmpDestination);

 

        Console::WriteLine("send {0} bytes to {1}", rc, igmpDestination->ToString());

    }

    return 0;

}

 

Next, build the project and make sure there is no error. Then, run the project. Any error will be thrown by the exception handlers. The following is the sample output.

 

C++ Raw Socket IGMP Program Example - building the completed project and running it from command line. The output sample shows the options available for the program

 

The following is the sample output when run at command prompt.

 

C++ Raw Socket IGMP Program Example - a sample output when run from command line with arguments suppplied  

 

C# Raw Socket IGMP Program Example

 

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

 

C# Raw Socket IGMP Program Example - creating a new console application in VS 2008

 

Next, rename the class to RawSocketIGMP to reflect the application that we are going to develop.

 

C# Raw Socket IGMP Program Example - renaming the source file automatically rename the class name

 

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

 

using System;

using System.Net;

using System.Net.Sockets;

using System.Collections;

// Reference the protocol header classes

using ProtocolHeaderDefinition;

 

Add the following method in the class.

 

static void usage()

{

            Console.WriteLine("Executable_file_name [-c send-count] [-g x.y.z.w] [-i a.b.c.d] [-p pad]");

            Console.WriteLine("Options:");

            Console.WriteLine("    -g x.y.z.w       - Multicast group to send query for");

            Console.WriteLine("    -i a.b.c.d       - Local interface to send query on");

            Console.WriteLine("    -p pad-bytes     - Number of pad bytes at end of packet");

            Console.WriteLine("    -c send-count    - Number of times to send query");

            Console.WriteLine("...Else, default values will be used...");

            Console.WriteLine();

}

 

Next, add the Main() code.

 

static void Main(string[] args)

{

            IPAddress groupAddress = IPAddress.Parse("234.6.7.8"), localAddress = IPAddress.Any;

            int padByteCount = 0, sendCount = 5;

 

            usage();

            Console.WriteLine();

 

            // Parse the command line

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

            {

                try

                {

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

                    {

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

                        {

                            case 'c':

                                // Number of times to send packet

                                sendCount = System.Convert.ToInt32(args[++i].ToString());

                                break;

                            case 'g':

                                // Multicast group

                                groupAddress = IPAddress.Parse(args[++i].ToString());

                                break;

                            case 'i':

                                // Local interface to send query from

                                localAddress = IPAddress.Parse(args[++i].ToString());

                                break;

                            case 'p':

                                // Amount of pad data

                                padByteCount = System.Convert.ToInt32(args[++i].ToString());

                                break;

                            default:

                                usage();

                                return;

                        }

                    }

                }

                catch

                {

                    usage();

                    return;

                }

            }

 

            // Display the parameter

            Console.WriteLine("Sending query for group: {0}", groupAddress.ToString());

            Console.WriteLine("Sending on interface   : {0}", localAddress.ToString());

            Console.WriteLine("Number of pad bytes    : {0}", padByteCount);

            Console.WriteLine("Send count             : {0}", sendCount);

 

            IgmpHeader igmpHeader = new IgmpHeader();

            Ipv4Header ipv4Header = new Ipv4Header();

            ArrayList headerList = new ArrayList();

            IPEndPoint igmpDestination = new IPEndPoint(IgmpHeader.AllSystemsAddress, 0),

            localEndpoint = new IPEndPoint(localAddress, 0);

            Socket igmpSocket;

            byte[ ] igmpPacket, padBytes;

 

            // Build the IPv4 header

            Console.WriteLine("Building the IPv4 header...");

            ipv4Header.Version = 4;

            ipv4Header.Protocol = (byte)ProtocolType.Igmp;

            ipv4Header.Ttl = 1;

            ipv4Header.Offset = 0;

            ipv4Header.Length = 20;

            ipv4Header.TotalLength = (ushort)System.Convert.ToUInt16(IgmpHeader.IgmpHeaderLength + padByteCount);

            ipv4Header.SourceAddress = localAddress;

            ipv4Header.DestinationAddress = IgmpHeader.AllSystemsAddress;

 

            // Add the header to the list of headers

            Console.WriteLine("Adding the header to the list of headers...");

            headerList.Add(ipv4Header);

 

            // Build the IGMP header

            igmpHeader.VersionType = IgmpHeader.IgmpMembershipQuery;

            igmpHeader.MaximumResponseTime = 100;

            igmpHeader.GroupAddress = groupAddress;

 

            // Allocate pad bytes as necessary

            Console.WriteLine("Allocating pad bytes as necessary...");

            padBytes = new byte[padByteCount];

 

            // Add the IGMP header to the list of headers

            Console.WriteLine("Adding the IGMP header to the list of headers...");

            headerList.Add(igmpHeader);

 

            // Build the packet

            Console.WriteLine("Building the packet...");

            igmpPacket = igmpHeader.BuildPacket(headerList, padBytes);

 

            // Create the raw socket

            Console.WriteLine("Creating the raw socket, Socket()...");

            igmpSocket = new Socket(

                groupAddress.AddressFamily,

                SocketType.Raw,

                ProtocolType.Igmp

                );

 

            // Bind to a local interface

            Console.WriteLine("Binding to a local interface, Bind()...");

            igmpSocket.Bind(localEndpoint);

 

            // Set the HeaderIncluded option

            Console.WriteLine("Setting the HeaderIncluded option...");

            igmpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, 1);

 

            // Send the packet the requested number of times

            Console.WriteLine("Send the packet the requested number of times...");

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

            {

                int rc = igmpSocket.SendTo(igmpPacket, igmpDestination);

 

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

            }

        }

 

We need to add references to the Protocol.cs so that all the definition defined in the ProtocolHeaderDefinition can be resolved. Select the project folder > Right click mouse > Select Add context menu > Select Existing Item context menu.

 

C# Raw Socket IGMP Program Example - adding the existing item into the project

 

Browse and find the Protocol.cs file created previously. Select the file and click Add.

 

C# Raw Socket IGMP Program Example - browsing ,finding and selecting the file to be included in the project

 

You can see the Protocol.cs file is included under the project folder as shown in the following Figure.

 

C# Raw Socket IGMP Program Example - the included source file can be seen in the Solution Explorer and the related header seems resolved

 

Next, build the project and make sure there is no error.

 

C# Raw Socket IGMP Program Example - building the project to check the validity of the custom made class and is accessible

 

Then, run the project. Any error will be thrown by the exception handlers.

 

C# Raw Socket IGMP Program Example - running the project

 

The following is the sample output.

 

C# Raw Socket IGMP Program Example - a sample output with default argument values

 

The following is the sample output when run at command prompt.

 

C# Raw Socket IGMP Program Example - a sample output with supplied argument run from the command line

 

 

 


 

< C# Raw Socket Ping Program Example (Cont...) | Main | .NET IP Multicasting & C++ Example >