< C++ .NET Client Socket Program Example | Main | C# Client Socket Example (Cont...) >

 


 

Chapter 8 Part 3:

Client (and Server) Sockets Communication

 

 

What do we have in this chapter 8 Part 3?

  1. C# Simple Client Server Socket Program Example

  2. C# Adding Simple Client Socket Project Program Example

 

 

C# Simple Client Server Socket Program Example

 

Create a console application project. You can use the project name as shown in the following Figure.

 

C# Simple Server Socket Program Example - a new console application project creation in Visual Studio 2008

 

Rename the class to ServerSocket by renaming the source file.

 

C# Simple Server Socket Program Example - renaming the source file automatically renaming the class name

 

C# Adding Simple Client Socket Project Program Example

 

Next, add a new project.

 

C# Simple Server Socket Program Example - adding another project in the existing solution

 

Select console application template and name it as SocketClient.

 

C# Simple Client Server Socket Program Example - adding a new console application project into existing solution

 

Rename the class to ClientSocket by renaming the source file.

 

C# Simple Client Server Socket Program Example - invoking the Rename menu to rename the source file

 

C# Simple Client Server Socket Program Example - renaming the source file

 

Let do the server coding. Add the following code to ServerSocket.cs.

 

// This is a simple TCP and UDP server. A socket of the requested type is created that

// waits for clients. For TCP, the server waits for an incoming TCP connection after which

// it receives a "request". The request is terminated by the client shutting down the connection.

// After the request is received, the server sends data in response followed by shutting down its

// connection and closing the socket. The UDP server simply waits for a datagram request. The

// request consists of a single datagram packet. The server then sends a number of responses to

// the source address of the request followed by a number of zero byte datagrams. The zero

// byte datagrams will indicate to the client that no more data will follow.

//

// usage:

//      Executable_file_name [-l bind-address] [-m message] [-n count] [-p port]");

//                       [-t tcp|udp] [-x size]

//        -l bind-address        Local address to bind to

//        -m message             Text message to format into send buffer

//        -n count               Number of times to send a message

//        -p port                Local port to bind to

//        -t udp | tcp           Indicates which protocol to use

//        -x size                Size of send and receive buffer

//

// sample usage:

//      The following command line invokes an IPv6 TCP server bound to the wildcard address (::)

//      and port 5150 that sends 10 messages of 1024 bytes filled with the string "hola". The

//      command line following the server's is the client side that can be used to connect to

//      the server. For the client substitute the appropriate IPv6 address of the server.

//

//          Executable_file_name -l :: -p 5150 -n 10 -m "hola" -x 1024 -t tcp

//          Executable_file_name -n 3ffe::1 -p 5150 -t tcp

//

//      The following command line invokes an IPv4 UDP server bound to a specific local interface

//      on port 5150 that sends 5 messages of 512 bytes filled with the string "response". The

//      second command line is an example of the client's command line used to connect to the server.

//      NOTE: For UDP the buffer size on client and server should match - otherwise, an exception

//            will be thrown since the smaller buffer won't be able to hold the larger received datagram.

//

//          Executable_file_name -l 10.10.10.1 -p 5150 -n 5 -m "response" -x 512 -t udp

//          Executable_file_name -n 10.10.10.1 -p 5150 -t udp -x 512

//

using System;

using System.Net;

using System.Net.Sockets;

 

namespace SimpleSocketCS

{

    /// <summary>

    /// This is a simple TCP and UDP based server.

    /// </summary>

    class ServerSocket

    {

        /// <summary>

        /// Winsock ioctl code which will disable ICMP errors from being propagated to a UDP socket.

        /// This can occur if a UDP packet is sent to a valid destination but there is no socket

        /// registered to listen on the given port.

        /// </summary>

        public const int SIO_UDP_CONNRESET = -1744830452;

 

        /// <summary>

        /// This routine repeatedly copies a string message into a byte array until filled.

        /// </summary>

        /// <param name="dataBuffer">Byte buffer to fill with string message</param>

        /// <param name="message">String message to copy</param>

        static public void FormatBuffer(byte[] dataBuffer, 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

            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;

                    }

                }

            }

        }

 

        /// <summary>

        /// Prints simple usage information.

        /// </summary>

        static void usage()

        {

            Console.WriteLine("Executable_file_name [-l bind-address] [-m message] [-n count] [-p port]");

            Console.WriteLine("                 [-t tcp|udp] [-x size]");

            Console.WriteLine("  -l bind-address        Local address to bind to");

            Console.WriteLine("  -m message             Text message to format into send buffer");

            Console.WriteLine("  -n count               Number of times to send a message");

            Console.WriteLine("  -p port                Local port to bind to");

            Console.WriteLine("  -t udp | tcp           Indicates which protocol to use");

            Console.WriteLine("  -x size                Size  of send and receive buffer");

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

        }

 

        /// <summary>

        /// This is the main routine that parses the command line and invokes the server with the

        /// given parameters. For TCP, it creates a listening socket and waits to accept a client

        /// connection. Once a client connects, it waits to receive a "request" message. The

        /// request is terminated by the client shutting down the connection. After the request is

        /// received, the server sends a response followed by shutting down its connection and

        /// closing the socket. For UDP, the socket simply listens for incoming packets. The "request"

        /// message is a single datagram received. Once the request is received, a number of datagrams

        /// are sent in return followed by sending a few zero byte datagrams. This way the client

        /// can determine that the response has completed when it receives a zero byte datagram.

        /// </summary>

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

        static void Main(string[ ] args)

        {

            string textMessage = "Server: ServerResponse";

            int localPort = 5150, sendCount = 10, bufferSize = 4096;

            IPAddress localAddress = IPAddress.Any;

            SocketType sockType = SocketType.Stream;

            ProtocolType sockProtocol = ProtocolType.Tcp;

 

            Console.WriteLine();

            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 'l':       // Local interface to bind to

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

                                break;

                            case 'm':       // Text message to put into the send buffer

                                textMessage = args[++i];

                                break;

                            case 'n':       // Number of times to send the response

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

                                break;

                            case 'p':       // Port number for the destination

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

                                break;

                            case 't':       // Specified TCP or UDP

                                i++;

                                if (String.Compare(args[i], "tcp", true) == 0)

                                {

                                    sockType = SocketType.Stream;

                                    sockProtocol = ProtocolType.Tcp;

                                }

                                else if (String.Compare(args[i], "udp", true) == 0)

                                {

                                    sockType = SocketType.Dgram;

                                    sockProtocol = ProtocolType.Udp;

                                }

                                else

                                {

                                    usage();

                                    return;

                                }

                                break;

                            case 'x':       // Size of the send and receive buffers

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

                                break;

                            default:

                                usage();

                                return;

                        }

                    }

                }

                catch

                {

                    usage();

                    return;

                }

            }

 

            Socket serverSocket = null;

 

            try

            {

                IPEndPoint localEndPoint = new IPEndPoint(localAddress, localPort), senderAddress = new IPEndPoint(localAddress, 0);

                Console.WriteLine("Server: IPEndPoint is OK...");

                EndPoint castSenderAddress;

                Socket clientSocket;

                byte[ ] receiveBuffer = new byte[bufferSize], sendBuffer = new byte[bufferSize];

                int rc;

 

                FormatBuffer(sendBuffer, textMessage);

 

                // Create the server socket

                serverSocket = new Socket(localAddress.AddressFamily, sockType, sockProtocol);

 

                Console.WriteLine("Server: Socket() is OK...");

                // Bind the socket to the local interface specified

                serverSocket.Bind(localEndPoint);

 

                Console.WriteLine("Server: {0} server socket bound to {1}", sockProtocol.ToString(), localEndPoint.ToString());

 

                if (sockProtocol == ProtocolType.Tcp)

                {

                    // If TCP socket, set the socket to listening

                    serverSocket.Listen(1);

                    Console.WriteLine("Server: Listen() is OK, I'm listening for connection buddy!");

                }

                else

                {

                    byte[ ] byteTrue = new byte[4];

 

                    // Set the SIO_UDP_CONNRESET ioctl to true for this UDP socket. If this UDP socket

                    //    ever sends a UDP packet to a remote destination that exists but there is

                    //    no socket to receive the packet, an ICMP port unreachable message is returned

                    //    to the sender. By default, when this is received the next operation on the

                    //    UDP socket that send the packet will receive a SocketException. The native

                    //    (Winsock) error that is received is WSAECONNRESET (10054). Since we don't want

                    //    to wrap each UDP socket operation in a try/except, we'll disable this error

                    //    for the socket with this ioctl call.

                    byteTrue[byteTrue.Length - 1] = 1;

                    serverSocket.IOControl(ServerSocket.SIO_UDP_CONNRESET, byteTrue, null);

                    Console.WriteLine("Server: IOControl() is OK...");

                }

 

                // Service clients in a loop

                while (true)

                {

                    if (sockProtocol == ProtocolType.Tcp)

                    {

                        // Wait for a client connection

                        clientSocket = serverSocket.Accept();

                        Console.WriteLine("Server: Accept() is OK...");

                        Console.WriteLine("Server: Accepted connection from: {0}", clientSocket.RemoteEndPoint.ToString());

 

                        // Receive the request from the client in a loop until the client shuts

                        //    the connection down via a Shutdown.

                        Console.WriteLine("Server: Preparing to receive using Receive()...");

                        while (true)

                        {

                            rc = clientSocket.Receive(receiveBuffer);

                           

                            Console.WriteLine("Server: Read {0} bytes", rc);

                            if (rc == 0)

                                break;

                        }

 

                        // Send the indicated number of response messages

                        Console.WriteLine("Server: Preparing to send using Send()...");

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

                        {

                            rc = clientSocket.Send(sendBuffer);

                            Console.WriteLine("Server: Sent {0} bytes", rc);

                        }

 

                        // Shutdown the client connection

                        clientSocket.Shutdown(SocketShutdown.Send);

                        Console.WriteLine("Server: Shutdown() is OK...");

                        clientSocket.Close();

                        Console.WriteLine("Server: Close() is OK...");

                    }

                    else

                    {

                        castSenderAddress = (EndPoint)senderAddress;

 

                        // Receive the initial request from the client

                        rc = serverSocket.ReceiveFrom(receiveBuffer, ref castSenderAddress);

                        Console.WriteLine("Server: ReceiveFrom() is OK...");

                        senderAddress = (IPEndPoint)castSenderAddress;

                        Console.WriteLine("Server: Received {0} bytes from {1}", rc, senderAddress.ToString());

 

                        // Send the response to the client the requested number of times

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

                        {

                            try

                            {

                                rc = serverSocket.SendTo(sendBuffer, senderAddress);

                                Console.WriteLine("Server: SendTo() is OK...");

                            }

                            catch

                            {

                                // If the sender's address is being spoofed we may get an error when sending

                                //    the response. You can test this by using IPv6 and using the RawSocket

                                //    sample to spoof a UDP packet with an invalid link local source address.

                                continue;

                            }

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

                        }

 

                        // Send several zero byte datagrams to indicate to client that no more data

                        //    will be sent from the server. Multiple packets are sent since UDP

                        //    is not guaranteed and we want to try to make an effort the client

                        //    gets at least one.

                        Console.WriteLine("Server: Preparing to send using SendTo(), on the way do sleeping, Sleep(250)...");

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

                        {

                            serverSocket.SendTo(sendBuffer, 0, 0, SocketFlags.None, senderAddress);

                            // Space out sending the zero byte datagrams a bit. UDP is unreliable and

                            //   the local stack can even drop them before even hitting the wire!

                            System.Threading.Thread.Sleep(250);

                        }

                    }

                }

            }

            catch (SocketException err)

            {

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

            }

            finally

            {

                // Close the socket if necessary

                if (serverSocket != null)

                {

                    Console.WriteLine("Server: Closing using Close()...");

                    serverSocket.Close();

                }

            }

        }

    }

}

 

 

 

Then, build the server program and make sure there is no error.

 

C# Simple Server Socket Program Example - building the server project independently

 

Then, run this program.

 

C# Simple Server Socket Program Example - running the server project independently

 

The following is a sample output.

 

C# Simple Server Socket Program Example - a sample of server output

 

The following is a sample output when the program runs at the command prompt.

 

C# Simple Server Socket Program Example - a sample output when run from command line

 

C# Simple Server Socket Program Example - a sample of server output ready for TCP connection

 

C# Simple Server Socket Program Example - a sample of server output ready for UDP connection

 

 

 


 

< C++ .NET Client Socket Program Example | Main | C# Client Socket Example (Cont...) >