< NegotiateStream Class Server Example | Main | AuthenticatedStream, StreamWriter & StreamReader Class Examples >

 


 

Chapter 2 Part 13:

Managed I/O - Streams, Readers, and Writers

 

 

What do we have in this chapter 2 Part 13?

  1. C++ NegotiateStream Client Program Example

  2. C# NegotiateStream Client Program Example

 

 

 

Note: If you want to experience a complete C++ .NET/C++-CLI programming tutorial please jump to Visual C++ .NET programming tutorial.

 

C++ NegotiateStream Client Example

 

Create a new CLR console application project and you might want to use NegotiatedStreamClientCP as the project and solution names.

 

C++ NegotiateStream Client Example - a new CLR console application project creation

 

Add the following code.

 

 

 

// NegotiatedStreamClientCP.cpp : main project file.

 

#include "stdafx.h"

 

using namespace System;

using namespace System::Net;

using namespace System::Net::Security;

using namespace System::Net::Sockets;

using namespace System::Text;

 

// The following class displays the properties of an authenticatedStream.

public ref class AuthenticatedStreamReporter

{

            public:

                        static void DisplayProperties( AuthenticatedStream^ stream )

                        {

                                    Console::WriteLine( L"IsAuthenticated: {0}", stream->IsAuthenticated );

                                    Console::WriteLine( L"IsMutuallyAuthenticated: {0}", stream->IsMutuallyAuthenticated );

                                    Console::WriteLine( L"IsEncrypted: {0}", stream->IsEncrypted );

                                    Console::WriteLine( L"IsSigned: {0}", stream->IsSigned );

                                    Console::WriteLine( L"IsServer: {0}", stream->IsServer );

                        }

};

 

public ref class ASynchronousAuthenticatingTcpClient

{

            private:

                        static TcpClient^ client = nullptr;

 

            public:

                        void AnotherDayAnotherMain()

                        {                                  

                                    // Establish the remote endpoint for the socket. For this example, use the local machine.

                                    Console::WriteLine( L"Using localhost as remote endpoint...");

                                    // IPHostEntry^ ipHostInfo = Dns::GetHostEntry( "localhost" );

                                    // You may try other remote point such as valid domain names and IP addresses

                                    IPHostEntry^ ipHostInfo = Dns::GetHostEntry(Dns::GetHostName());

                                    IPAddress^ ipAddress = ipHostInfo->AddressList[0];

 

                                    try

                                    {

                                    // Client and server use port 1234.

                                    Console::WriteLine( L"Using {0} port 1234...", ipAddress);

                                    IPEndPoint^ remoteEP = gcnew IPEndPoint( ipAddress,1234 );

                                   

                                    // Create a TCP/IP socket.

                                    Console::WriteLine( L"Creating a TCP/IP socket...");

                                    // UdpClient and TcpClient create a IPv4 socket in the default constructor Then passing iPv6 will fail...

                                    // client = gcnew TcpClient;

                                    // So use this...

                                    client = gcnew TcpClient(ipAddress->AddressFamily);

                                   

                                    // Connect the socket to the remote endpoint.

                                    Console::WriteLine( L"Connecting the socket to the remote endpoint...");

                                    client->Connect( remoteEP );

                                    Console::WriteLine( L"Client connected to {0}.", remoteEP->ToString() );

                                   

                                    // Ensure the client does not close when there is still data to be sent to the server.

                                    Console::WriteLine( L"Don't close if there is data...");

                                    client->LingerState = (gcnew LingerOption( true,0 ));

                                   

                                    // Request authentication.

                                    Console::WriteLine( L"Requesting authentication...");

                                    NetworkStream^ clientStream = client->GetStream();

                                    NegotiateStream^ authStream = gcnew NegotiateStream( clientStream,false );

                                   

                                    // Pass the NegotiateStream as the AsyncState object so that it is available to the callback delegate.

                                    Console::WriteLine( L"Passing the NegotiateStream as the AsyncState object...");

                                    IAsyncResult^ ar = authStream->BeginAuthenticateAsClient( gcnew AsyncCallback( EndAuthenticateCallback ), authStream );

                                   

                                    Console::WriteLine( L"Client waiting for authentication..." );

                                   

                                    // Wait until the result is available.

                                    Console::WriteLine( L"Waiting until the result is available...");

                                    ar->AsyncWaitHandle->WaitOne();

                                   

                                    // Display the properties of the authenticated stream.

                                    Console::WriteLine( L"Displaying the properties of the authenticated stream...");

                                    AuthenticatedStreamReporter::DisplayProperties( authStream );

 

                                    // Send a message to the server. Encode the test data into a byte array.

                                    array<Byte>^message = Encoding::UTF8->GetBytes( L"Client: Hello buddy..." );

                                    ar = authStream->BeginWrite(message, 0, message->Length, gcnew AsyncCallback( EndWriteCallback ), authStream );

                                    ar->AsyncWaitHandle->WaitOne();

                                    Console::WriteLine( L"Sent {0} bytes.", message->Length );

                                   

                                    // Close the client connection.

                                    Console::WriteLine( L"Closing the client connection...");

                                    authStream->Close();

                                    Console::WriteLine( L"Client closed..." );

                                    }

                                    catch(Exception^ err)

                                    {

                                                Console::WriteLine("Got some errors:\n   " + err->Message);

                                                Console::WriteLine("You may need to run the server first...");

                                    }

                        }

                       

                        // The following method is called when the authentication completes.

                        static void EndAuthenticateCallback( IAsyncResult^ ar )

                        {

                                    Console::WriteLine( L"Client ending authentication..." );

                                    NegotiateStream^ authStream = dynamic_cast<NegotiateStream^>(ar->AsyncState);

                                    // End the asynchronous operation.

                                    authStream->EndAuthenticateAsClient( ar );

                                    // Console.WriteLine("AllowedImpersonation: {0}", authStream.AllowedImpersonation);

                        }

                       

                        // The following method is called when the write operation completes.

                        static void EndWriteCallback( IAsyncResult^ ar )

                        {

                                    Console::WriteLine( L"Client ending write operation..." );

                                    NegotiateStream^ authStream = dynamic_cast<NegotiateStream^>(ar->AsyncState);

                                    // End the asynchronous operation.

                                    authStream->EndWrite( ar );

                        }

};

 

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

{

            ASynchronousAuthenticatingTcpClient^ aatc = gcnew ASynchronousAuthenticatingTcpClient;

            aatc->AnotherDayAnotherMain();

            return 0;

}

 

Build and run the project.

 

C++ NegotiateStream Client Example - a sample output when run from the command prompt

 

The following are output examples when running both the server and client program on localhost. Unblock the Windows security alert if any.

 

C++ NegotiateStream Client Example - Windows Security alert box  

 

Firstly, we run the server and start listening for connection.

 

C++ NegotiateStream Client Example - running a server and start listening connection

 

Then, we run the client on another Windows console.

 

C++ NegotiateStream Client Example - running a client program

 

The following screenshot shows the server program after the communication completed.

 

 

C# NegotiateStream Client Example

 

The following code example demonstrates the client side (NegotiateStreamClientCS) of a client-server connection that uses the NegotiateStream. The client authenticates and sends a message to the server asynchronously. Create a new console application project. You can use the solution and project name as NegotiateStreamClientCS.

 

using System;

using System.Collections.Generic;

using System.Net;

using System.Net.Security;

using System.Net.Sockets;

using System.Text;

 

namespace NegotiateStreamClient

{

    public class ASynchronousAuthenticatingTcpClient

    {

        static TcpClient client = null;

 

        public static void Main(String[] args)

        {

            // Establish the remote endpoint for the socket. For this example, use the local machine.

            IPHostEntry ipHostInfo = Dns.GetHostEntry("localhost");

            IPAddress ipAddress = ipHostInfo.AddressList[0];

            // Client and server use port 11000.

            IPEndPoint remoteEP = new IPEndPoint(ipAddress, 11000);

            // Create a TCP/IP socket.

            client = new TcpClient();

            // Connect the socket to the remote endpoint.

            client.Connect(remoteEP);

            Console.WriteLine("Client connected to {0}.", remoteEP.ToString());

            // Ensure the client does not close when there is still data to be sent to the server.

            client.LingerState = (new LingerOption(true, 0));

            // Request authentication.

            NetworkStream clientStream = client.GetStream();

            NegotiateStream authStream = new NegotiateStream(clientStream, false);

            // Pass the NegotiateStream as the AsyncState object so that it is available to the callback delegate.

            IAsyncResult ar = authStream.BeginAuthenticateAsClient(new AsyncCallback(EndAuthenticateCallback),authStream);

            Console.WriteLine("Client waiting for authentication...");

            // Wait until the result is available.

            ar.AsyncWaitHandle.WaitOne();

            // Display the properties of the authenticated stream.

            AuthenticatedStreamReporter.DisplayProperties(authStream);

            // Send a message to the server. Encode the test data into a byte array.

            byte[ ] message = Encoding.UTF8.GetBytes("Hello from the client.");

            ar = authStream.BeginWrite(message, 0, message.Length, new AsyncCallback(EndWriteCallback), authStream);

            ar.AsyncWaitHandle.WaitOne();

            Console.WriteLine("Sent {0} bytes.", message.Length);

            // Close the client connection.

            authStream.Close();

            Console.WriteLine("Client closed.");

        }

        // The following method is called when the authentication completes.

        public static void EndAuthenticateCallback(IAsyncResult ar)

        {

            Console.WriteLine("Client ending authentication...");

            NegotiateStream authStream = (NegotiateStream)ar.AsyncState;

            // End the asynchronous operation.

            authStream.EndAuthenticateAsClient(ar);

            // Console.WriteLine("AllowedImpersonation: {0}", authStream.AllowedImpersonation);

        }

        // The following method is called when the write operation completes.

        public static void EndWriteCallback(IAsyncResult ar)

        {

            Console.WriteLine("Client ending write operation...");

            NegotiateStream authStream = (NegotiateStream)ar.AsyncState;

            // End the asynchronous operation.

            authStream.EndWrite(ar);

        }

    }

 

    // The following class displays the properties of an authenticatedStream.

    public class AuthenticatedStreamReporter

    {

        public static void DisplayProperties(AuthenticatedStream stream)

        {

            Console.WriteLine("IsAuthenticated: {0}", stream.IsAuthenticated);

            Console.WriteLine("IsMutuallyAuthenticated: {0}", stream.IsMutuallyAuthenticated);

            Console.WriteLine("IsEncrypted: {0}", stream.IsEncrypted);

            Console.WriteLine("IsSigned: {0}", stream.IsSigned);

            Console.WriteLine("IsServer: {0}", stream.IsServer);

        }

    }

}

 

An output sample:

 

C# NegotiateStream Client Example - a sample console mode application output with thrown exception

 

Running both the client and server programs. Firstly, run the server program and then the client program. A sample output is shown below.

 

An output sample:

 

 

 

 


 

< NegotiateStream Class Server Example | Main | AuthenticatedStream, StreamWriter & StreamReader Class Examples >