< NetworkStream Sender Examples | Main | CryptoStream Class Examples >

 


 

Chapter 2 Part 8:

Managed I/O - Streams, Readers, and Writers

 

 

What do we have in this chapter 2 Part 8?

  1. Composable Streams

  2. BufferedStream Class

  3. C++ BufferedStream Program Example

  4. C# BufferedStream Program Example

  5. VB .NET BufferedStream Program Example

 

 

 

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

 

Composable Streams

 

Composable stream classes are streams that can perform I/O on top of another underlying stream. It’s important to understand that the underlying stream can be a base stream or even another composable stream. As we mentioned earlier, composable streams have constructors that accept a stream as a parameter. This is a powerful idea because you can layer I/O techniques for reading data from and writing data to resources. For example, if you want to encrypt some data and save it to a file, you could simply open a base stream-FileStream-followed by a composable stream, CryptoStream and then begin writing encrypted data to a file, as shown in Figure 2-4. In the .NET Framework version 1, only two composable streams are available: BufferedStream and CryptoStream.

 

.NET layering one stream on top of another stream

 

Figure 2-4: Layering one stream on top of another stream

 

Take note that in the .NET Framework version 2, there is a composable stream to handle Secure Sockets Layer (SSL) communications over a stream. This new stream will allow you to use streams to communicate to an SSL server over a network by layering an SSL-composable stream over a network stream.

 

BufferedStream Class

 

BufferedStream is an interesting class that’s designed to improve I/O performance when either reading or writing to another stream. This composable stream can be very useful, especially if your application performs I/O by reading or writing data in very small amounts. The class maintains an internal buffer to cache or collect the data, and at some point it will automatically flush data to the next stream or hold data until your application is ready to read from the stream.

By default, the BufferedStream class maintains a buffer of 4096 bytes. You can override the default by specifying any size buffer through the constructor, depending on your application’s needs. The buffer can be used only for read or write operations, but not for both at the same time. If your application alternates between Read() and Write() calls continuously, the buffer will not be used very effectively. So, if you’re developing an application that makes a series of either Read() or Write() calls using small amounts of data, the BufferedStream class can potentially improve I/O performance with operating system resources.

 

C++ BufferedStream Example

 

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

 

C++ BufferedStream program example using VS 2008

 

Add the following code.

 

// BufferedStreamSampleCP.cpp : main project file.

// <summary>

// This sample demonstrates how to use the BufferedStream class to

// improve IO performance on a network stream. This sample is a

// revision of the network stream Sender sample that includes the

// composable stream BufferedStream.

//

// sample has 2 optional parameters that can be used:

// Sender [/server <server IP>] [/port <port>]

// By default this application will connect to the server on the same machine using TCP port 5150.

// </summary>

 

#include "stdafx.h"

 

using namespace System;

using namespace System::IO;

using namespace System::Net;

using namespace System::Net::Sockets;

 

// <summary>

// The main entry point for the application.

// </summary>

[STAThread]

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

{

    // The following are the default values

    String^ ServerName = "127.0.0.1";

    int Port = 5150;

 

            args = Environment::GetCommandLineArgs();

           

            if(args->Length != 1)

            {

                        // Parse command line arguments if any

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

                        {

                                    if (String::Compare(args[i], "/server", true) == 0)

                                    {

                                         // The server's name we will connect to

                                         ServerName = args[++i]->ToString();

                                     }

                                    else if (String::Compare(args[i], "/port", true) == 0)

                                    {

                                        // The port on which the server is listening

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

                                    }

                      }

            }

            else

            {

                        Console::WriteLine("Usage: {0} [/server <server IP>] [/port <port>]", args[0]);

                        return 0;

            }

 

    Socket^ ClientSocket = nullptr;

 

    try

    {

        // Let's connect to a listening server

        Console::WriteLine("Connecting to listening server...");

        try

        {

            ClientSocket = gcnew Socket(AddressFamily::InterNetwork, SocketType::Stream, ProtocolType::IP);

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

        }

        catch (Exception^ e)

        {

            throw gcnew Exception("Failed to create client Socket: " + e->Message);

        }

        IPEndPoint^ ServerEndPoint = gcnew IPEndPoint(IPAddress::Parse(ServerName), Convert::ToInt16(Port));

        try

        {

             ClientSocket->Connect(ServerEndPoint);

             Console::WriteLine("Connect() is OK...");

        }

        catch (Exception^ e)

        {

            throw gcnew Exception("Failed to connect client Socket: " + e->Message);

        }

    }

    catch (Exception^ e)

    {

        Console::WriteLine(e->Message);

        Console::WriteLine("Closing Socket...");

        ClientSocket->Close();

        return 0;

    }

    // Let's create a network stream to communicate over the connected Socket.

    NetworkStream^ ClientNetworkStream = nullptr;

 

    try

    {

        try

        {

            // Setup a network stream on the client Socket

            Console::WriteLine("Instantiate NetworkStream object...");

            ClientNetworkStream = gcnew NetworkStream(ClientSocket, true);

        }

        catch (Exception^ e)

        {

            // We have to close the client socket here because the network stream did not take ownership of the socket.

            throw gcnew Exception("Failed to create a NetworkStream with error: " + e->Message);

            Console::WriteLine("Closing client Socket...");

            ClientSocket->Close();

        }

    }

    catch (Exception^ e)

    {

        Console::WriteLine(e->Message);

        Console::WriteLine("Closing client NetworkStream...");

        ClientNetworkStream->Close();

        return 0;

    }

 

    BufferedStream^ ClientBufferedStream = nullptr;

 

    try

    {

        try

        {

            // Setup a network stream on the client Socket

            Console::WriteLine("Instantiate BufferedStream object...");

            ClientBufferedStream = gcnew BufferedStream(ClientNetworkStream);

        }

        catch (Exception^ e)

        {

            throw gcnew Exception("Failed to create a BufferedStream with error: " + e->Message);

        }

 

        try

        {

            Console::WriteLine("Writing/sending data...");

            array< Byte >^ Buffer = gcnew array< Byte >(1);

 

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

            {

                Buffer[0] = (Byte)i;

                ClientBufferedStream->Write(Buffer, 0, Buffer->Length);

            }

           Console::WriteLine("We wrote 200 bytes one byte at a time to the server.");

        }

        catch (Exception^ e)

        {

            throw gcnew Exception("Failed to write to client BufferedStream with error: " + e->Message);

        }

    }

    catch (Exception^ e)

    {

           Console::WriteLine(e->Message);

    }

    finally

    {

        // We are finished with the Stream so we will close it.

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

        ClientBufferedStream->Close();

    }

return 0;

}

 

Build and run the project. The following is output example.

 

C++ BufferedStream console output example

 

Let test this program against receiver program. In this case we use the NetworkStreamSampleCPReceiver program. Firstly, run the receiver program.

 

C++ BufferedStream Example - Receiver/server is listening for connection

 

Then run the BufferedStreamSampleCP program.

 

C++ BufferedStream sender output example

 

The following is the screenshot for the received data when the communication was completed.

 

  C++ BufferedStream Example - A screenshot for the received data when the communication was completed

 

C# BufferedStream Example

 

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

 

C# BufferedStream program example using VS 2008

 

Add the following code.

 

using System;

using System.IO;

using System.Net;

using System.Net.Sockets;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

// <summary>

// This sample demonstrates how to use the BufferedStream class to

// improve IO performance on a network stream. This sample is a

// revision of the network stream Sender sample that includes the composable stream BufferedStream.

//

// sample has 2 optional parameters that can be used:

// Sender [/server <server IP>] [/port <port>]

// By default this application will connect to the server on the same machine using TCP port 5150.

// </summary>

namespace BufferedStreamSampleCS

{

    class Program

    {

        // <summary>

        // The main entry point for the application.

        // </summary>

        [STAThread]

        static void Main(string[] args)

        {

            // The following is the default values

            string ServerName = "127.0.0.1";

            int Port = 5150;

 

            // Parse command line arguments if any

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

            {

                try

                {

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

                    {

                        // The server's name we will connect to

                        ServerName = args[++i].ToString();

                    }

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

                    {

                        // The port on which the server is listening

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

                    }

                }

                catch (System.IndexOutOfRangeException)

                {

                    Console.WriteLine("Usage: Executable_file_name [/server <server IP>] [/port <port>]");

                    return;

                }

            }

 

            Socket ClientSocket = null;

 

            try

            {

                // Let's connect to a listening server

                try

                {

                    ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);

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

                }

                catch (Exception e)

                {

                    throw new Exception("Failed to create client Socket: " + e.Message);

                }

                IPEndPoint ServerEndPoint = new IPEndPoint(IPAddress.Parse(ServerName), Convert.ToInt16(Port));

                try

                {

                    ClientSocket.Connect(ServerEndPoint);

                    Console.WriteLine("Connect() is OK...");

                }

                catch (Exception e)

                {

                    throw new Exception("Failed to connect client Socket: " + e.Message);

                }

            }

            catch (Exception e)

            {

                Console.WriteLine(e.Message);

                ClientSocket.Close();

                return;

            }

 

            // Let's create a network stream to communicate over the connected Socket.

            NetworkStream ClientNetworkStream = null;

            try

            {

                try

                {

                    // Setup a network stream on the client Socket

                    Console.WriteLine("Instantiate NetworkStream object...");

                    ClientNetworkStream = new NetworkStream(ClientSocket, true);

                }

                catch (Exception e)

                {

                    // We have to close the client socket here because the network stream did not take ownership of the socket.

                    ClientSocket.Close();

                    throw new Exception("Failed to create a NetworkStream with error: "  + e.Message);

                }

            }

            catch (Exception e)

            {

                Console.WriteLine(e.Message);

                ClientNetworkStream.Close();

                return;

            }

 

            BufferedStream ClientBufferedStream = null;

 

            try

            {

                try

                {

                    // Setup a network stream on the client Socket

                    Console.WriteLine("Instantiate BufferedStream object...");

                    ClientBufferedStream = new BufferedStream(ClientNetworkStream);

                }

                catch (Exception e)

                {

                    throw new Exception("Failed to create a BufferedStream with error: " + e.Message);

                }

 

                try

                {

                    Console.WriteLine("Writing/sending data...");

                    byte[] Buffer = new byte[1];

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

                    {

                        Buffer[0] = (byte)i;

                        ClientBufferedStream.Write(Buffer, 0, Buffer.Length);

                    }

                    Console.WriteLine("We wrote 200 bytes one byte at a time to the server.");

                }

                catch (Exception e)

                {

                    throw new Exception("Failed to write to client BufferedStream with error: " + e.Message);

                }

            }

            catch (Exception e)

            {

                Console.WriteLine(e.Message);

            }

            finally

            {

                // We are finished with the Stream so we will close it.

                ClientBufferedStream.Close();

            }

        }

    }

}

 

An output sample:

 

C# BufferedStream Example - output sample

 

By using the previous receiver program, we have the following sample output. Firstly run the receiver program and then run the sender program.

 

C# BufferedStream Example - receiver and sender output sample in action

 

VB .NET BufferedStream Example

 

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

 

VB .NET BufferedStream Example - console mode project creation

 

Add the following code.

 

 

Imports System

Imports System.IO

Imports System.Net

Imports System.Net.Sockets

 

'This sample demonstrates how to use the BufferedStream class to

' improve IO performance on a network stream. This sample is a

' revision of the network stream Sender sample that includes the composable stream BufferedStream.

'

' This sample has 2 optional parameters that can be used:

' Sender [/server <server IP>] [/port <port>]

' By default this application will connect to the server on the same machine using TCP port 5150.

Module Module1

    'The main entry point for the application.

    Sub Main()

        ' The following is the default values

        Dim ServerName As String = "127.0.0.1"

        Dim Port As Integer = 5150

 

        ' Parse command line arguments if any

        Dim args As String() = Environment.GetCommandLineArgs()

        Dim i As Integer

 

        For i = 1 To args.Length - 1

            Try

                If args(i) = "/server" Then

                    ' The server's name we will connect to

                    i = i + 1

                    ServerName = args(i).ToString()

                ElseIf args(i) = "/port" Then

                    ' The port on which the server is listening

                    i = i + 1

                    Port = System.Convert.ToInt32(args(i).ToString())

                End If

            Catch e As System.IndexOutOfRangeException

                Console.WriteLine("Usage: Sender [/server <server IP>] [/port <port>]")

                Exit Sub

            End Try

        Next

 

        Dim ClientSocket As Socket = Nothing

 

        Try

            ' Let's connect to a listening server

            Try

                ClientSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP)

                Console.WriteLine("Socket() is OK...")

            Catch e As Exception

                Throw New Exception("Failed to create client Socket: " + e.Message)

            End Try

 

            Dim ServerEndPoint As IPEndPoint = New IPEndPoint(IPAddress.Parse(ServerName), Convert.ToInt16(Port))

 

            Try

                ClientSocket.Connect(ServerEndPoint)

                Console.WriteLine("Connect() is OK...")

            Catch e As Exception

                Throw New Exception("Failed to connect client Socket: " + e.Message)

            End Try

        Catch e As Exception

            Console.WriteLine(e.Message)

            ClientSocket.Close()

            Exit Sub

        End Try

 

        ' Let's create a network stream to communicate over the connected Socket.

        Dim ClientNetworkStream As NetworkStream = Nothing

 

        Try

            Try

                ' Setup a network stream on the client Socket

                ClientNetworkStream = New NetworkStream(ClientSocket, True)

                Console.WriteLine("Instantiate NetworkStream is OK...")

            Catch e As Exception

                ' We have to close the client socket here because the network stream did not take ownership of the socket.

                ClientSocket.Close()

                Throw New Exception("Failed to create a NetworkStream with error: " + e.Message)

            End Try

        Catch e As Exception

            Console.WriteLine(e.Message)

            ClientNetworkStream.Close()

            Exit Sub

        End Try

 

        Dim ClientBufferedStream As BufferedStream = Nothing

 

        Try

            Try

                ' Setup a network stream on the client Socket

                ClientBufferedStream = New BufferedStream(ClientNetworkStream)

                Console.WriteLine("Instantiate BufferedStream is OK...")

            Catch e As Exception

                Throw New Exception("Failed to create a BufferedStream with error: " + e.Message)

            End Try

 

            Try

                Dim Buffer(1) As Byte

 

                Console.WriteLine("Writing/sending some data...")

                For i = 1 To 200

                    Buffer(0) = i

                    ClientBufferedStream.Write(Buffer, 0, Buffer.GetUpperBound(0))

                Next

                Console.WriteLine("We wrote 200 bytes one byte at a time to the server.")

            Catch e As Exception

                Throw New Exception("Failed to write to client BufferedStream with error: " + e.Message)

            End Try

        Catch e As Exception

            Console.WriteLine(e.Message)

        Finally

            ' We are finished with the Stream so we will close it.

            ClientBufferedStream.Close()

        End Try

    End Sub

End Module

 

An output sample:

 

VB .NET BufferedStream Example -sample output

 

Running both the previous VB receiver program and this example giving the following output.

 

VB .NET BufferedStream Example - a sample sender and receiver in action

 

 

 


 

< NetworkStream Sender Examples | Main | CryptoStream Class Examples >