< Adding C# ICMP & Ipv6 Echo Request & UDP Header Classes 5 | Main | C# Raw UDP Socket Program Example >

 


 

Chapter 8 Part 18: Client (and Server) Sockets Communication

 

 

What do we have in this chapter 8 Part 18?

  1. C++ Raw UDP Socket Program Example

 

 

C++ Raw UDP Socket Program Example

 

Create a new CLR console application project and you might use the project and solution names as shown in the following Figure.

 

C++ Raw UDP Socket Program Example - creating a new CLR console application project in Visual Studio 2008 IDE

 

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 to the protocol header classes

using namespace ProtocolHeaderDefinitionCP;

 

Then, add the reference to the header definition in the project.

 

C++ Raw UDP Socket Program Example - Invoking the project's References page

 

C++ Raw UDP Socket Program Example - adding a new project reference

 

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

 

C++ Raw UDP Socket Program Example - selecting the DLL file

 

C++ Raw UDP Socket Program Example - the new reference can be seen under the Name column od the References: field

 

Build the project to make sure the reference to the ProtocolHeaderDefinitionCP is working.

 

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

 

Make sure there is no build error.

 

C++ Raw UDP Socket Program Example - making sure there is no error as can be seen in the Output window

 

Then, adds the following usage() function.

 

static void usage()

{

    Console::WriteLine("Usage: Executable_file_name [-as source-addr] [-ad dest-addr] [-ps source-port]");

    Console::WriteLine("                  [-pd dest-port] [-x payload-size] [-n send-count] [-b bind-addr]");

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

    Console::WriteLine("     -as source-addr     Source address for IP packet");

    Console::WriteLine("     -ad dest-addr       Destination address for IP packet");

    Console::WriteLine("     -ps source-port     Source port for UDP packet");

    Console::WriteLine("     -pd dest-port       Destination port for UDP packet");

    Console::WriteLine("     -b  bind-addr       Local address to bind raw socket to");

    Console::WriteLine("     -x  payload-size    Number of bytes for UDP payload");

    Console::WriteLine("     -n  send-count      Number of times to send packet");

}

 

 

 

Next, add the main() code.

 

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

{

    // Default/initial values, the source should be a spoofed IP :-)

    IPAddress^ sourceAddress = IPAddress::Parse( "1.1.1.1" );

    IPAddress^ destAddress   = IPAddress::Parse( "2.2.2.2" );

    IPAddress^ bindAddress   = IPAddress::Any;

    unsigned short  sourcePort = 5150, destPort   = 1234;

    int messageSize = 16, sendCount   = 5;

 

// Parse the command line

if(args->Length != 0)

{

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

{

    try

    {

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

        {

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

            {

                case 'a':

                 // Address parameter: source or destination

                 if ( Char::ToLower( args[i][2] ) == 's' )

                 {

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

                    }

                    else if ( Char::ToLower( args[i][2] ) == 'd' )

                    {

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

                    }

                    else

                    {

                        usage();

                        return 0;

                    }

                    break;

                case 'b':

                    // Local address to bind the socket to

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

                    break;

                case 'p':

                    // Port parameter: source or destination

                    if ( Char::ToLower( args[i][2] ) == 's' )

                    {

                        sourcePort = Convert::ToUInt16( args[ ++i ]->ToString() );

                    }

                    else if ( Char::ToLower( args[i][2] ) == 'd' )

                    {

                        destPort = Convert::ToUInt16( args[ ++i ]->ToString() );

                    }

                    else

                    {

                        usage();

                        return 0;

                    }

                    break;

                case 'x':

                    // Size of message to send

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

                    break;

                case 'n':

                    // Number of times to send message

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

                    break;

                default:

                    usage();

                    return 0;

            }

        }                   

    }

    catch(Exception^ err)

    {

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

        usage();

        return 0;

    }

}

}

else

{

        usage();

        return 0;

}

 

// Make sure parameters are consistent

if ( ( sourceAddress->AddressFamily != destAddress->AddressFamily ) || ( sourceAddress->AddressFamily != bindAddress->AddressFamily) )

{

    Console::WriteLine("Source and destination address families don't match!");

    usage();

    return 0;

}

 

// Print the command line parameters

Console::WriteLine("Source address : {0}   \tPort: {1}", sourceAddress->ToString(), sourcePort.ToString() );

Console::WriteLine("Dest   address : {0}   \tPort: {1}", destAddress->ToString(), destPort.ToString() );

Console::WriteLine("Local interface: {0}", bindAddress->ToString() );

Console::WriteLine("Message size   : {0}", messageSize);

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

 

// Start building the headers

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

array<Byte>^  builtPacket;

array<Byte>^  payLoad = gcnew array<Byte>(messageSize);

UdpHeader^      udpPacket = gcnew UdpHeader();

ArrayList^      headerList = gcnew ArrayList();

Socket^         rawSocket = nullptr;

SocketOptionLevel   socketLevel = SocketOptionLevel::IP;

 

// Initialize the payload

Console::WriteLine("Initialize the payload...");

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

    payLoad[i] = (Byte) '#';

 

// Fill out the UDP header first

Console::WriteLine("Filling out the UDP header...");

udpPacket->SourcePort        = sourcePort;

udpPacket->DestinationPort   = destPort;

udpPacket->Length            = (unsigned short)(UdpHeader::UdpHeaderLength + messageSize);

udpPacket->Checksum          = 0;

 

if ( sourceAddress->AddressFamily == AddressFamily::InterNetwork )

{

    Ipv4Header^      ipv4Packet = gcnew Ipv4Header();

 

    // Build the IPv4 header

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

    ipv4Packet->Version      = 4;

    ipv4Packet->Protocol     = (Byte) ProtocolType::Udp;

    ipv4Packet->Ttl          = 2;

    ipv4Packet->Offset       = 0;

    ipv4Packet->Length       = (Byte) Ipv4Header::Ipv4HeaderLength;

    ipv4Packet->TotalLength  = (unsigned short) Convert::ToUInt16( Ipv4Header::Ipv4HeaderLength + UdpHeader::UdpHeaderLength + messageSize );

    ipv4Packet->SourceAddress        = sourceAddress;

    ipv4Packet->DestinationAddress   = destAddress;

 

    // Set the IPv4 header in the UDP header since it is required to calculate the

    //    pseudo header checksum

    Console::WriteLine("Setting the IPv4 header for pseudo header checksum...");

    udpPacket->ipv4PacketHeader = ipv4Packet;

 

    // Add IPv4 header to list of headers -- headers should be added in th order

    //    they appear in the packet (i.e. IP first then UDP)

    Console::WriteLine("Adding the IPv4 header to the list of header, encapsulating packet...");

    headerList->Add( ipv4Packet );  

 

     socketLevel = SocketOptionLevel::IP;

}

else if ( sourceAddress->AddressFamily == AddressFamily::InterNetworkV6 )

{

    Ipv6Header^  ipv6Packet = gcnew Ipv6Header();

 

    // Build the IPv6 header

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

    ipv6Packet->Version          = 6;

    ipv6Packet->TrafficClass     = 1;

    ipv6Packet->Flow             = 2;

    ipv6Packet->HopLimit         = 2;

    ipv6Packet->NextHeader       = (Byte) ProtocolType::Udp;

    ipv6Packet->PayloadLength    = (unsigned short) ( UdpHeader::UdpHeaderLength + payLoad->Length );

    ipv6Packet->SourceAddress        = sourceAddress;

    ipv6Packet->DestinationAddress   = destAddress;

 

    // Set the IPv6 header in the UDP header since it is required to calculate the

    //    pseudo header checksum

    Console::WriteLine("Setting the IPv6 header for pseudo header checksum...");

    udpPacket->ipv6PacketHeader = ipv6Packet;

 

    // Add the IPv6 header to the list of headers - headers should be added in the order

    //    they appear in the packet (i.e. IP first then UDP)

    Console::WriteLine("Adding the IPv6 header to the list of header, encapsulating packet...");

    headerList->Add( ipv6Packet );

    socketLevel = SocketOptionLevel::IPv6;

}

 

// Add the UDP header to list of headers after the IP header has been added

Console::WriteLine("Adding the UDP header to the list of header, after IP header...");

headerList->Add( udpPacket );

 

// Convert the header classes into the binary on-the-wire representation

Console::WriteLine("Converting the header classes into the binary...");

builtPacket = udpPacket->BuildPacket( headerList, payLoad );

 

// Create the raw socket for this packet

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

rawSocket = gcnew Socket(sourceAddress->AddressFamily, SocketType::Raw, ProtocolType::Udp);

 

// Bind the socket to the interface specified

Console::WriteLine("Binding the socket to the specified interface using Bind()...");

rawSocket->Bind( gcnew IPEndPoint( bindAddress, 0 ) );

 

// Set the HeaderIncluded option since we include the IP header

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

rawSocket->SetSocketOption( socketLevel, SocketOptionName::HeaderIncluded, 1 );

try

{

    // Send the packet!

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

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

    {

        int rc = rawSocket->SendTo(builtPacket, gcnew IPEndPoint(destAddress, destPort));

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

    }

}

catch (SocketException^ err)

{

    Console::WriteLine("Socket error occurred: {0}", err->Message);

    // http://msdn.microsoft.com/en-us/library/ms740668.aspx

}

finally

{

    // Close the socket

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

    rawSocket->Close();

}

    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.

 

C++ Raw UDP Socket Program Example - running the project (without debugging)

 

The following is the sample output.

 

C++ Raw UDP Socket Program Example - a sample output

 

C++ Raw UDP Socket Program Example - a sample output with arguments

 

C++ Raw UDP Socket Program Example - another sample output with argument values

 

 

 


 

< Adding C# ICMP & Ipv6 Echo Request & UDP Header Classes 5 | Main | C# Raw UDP Socket Program Example >