Pages

Search

Tuesday, February 28, 2012

Transferring File Using Name Pipe and Serialization


Named Pipe is usually used for inter process communication. The example below demonstrates the same. Below sample helps to transfer file content from NamedPipeServer to NamedPipeClient.
Creating an instance to “NamedPipeServerStream” class providing a pipe name will register a named pipe server. A Named Pipe client can receive the stream from a specific Named Pipe Server based on the name.
This is something like a dedicated channel through which processes can communicate using NamedPipe Name. 
Using NamedPipe a process can also transfer messages (string).

In the below example, NamedPipeServer is started or registered with name “File Transfer”.
The NamedPipeServer reads the content of a source file and creates an instance for “TransferFile” class setting the attributes such as source file name and file content (stream).
Server then serializes the "TransferFile" object and writes to the stream.


NamedPipeClient connects to the NamedPipeServer based whose server name is “File Transfer”.
and reads the stream. After reading the stream, Client deserializes to get the “TransferFile” object.
from the “FileTransfer” object, client creates the target file in specific directory with name from “FileName” attribute and content(byte[]) from “FileContent”.

TransferFile.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace FileTransfer
{
    //file transfer class (serializable)
    [Serializable]
    public class TransferFile
    {
        public string FileName;
        public Stream FileContent;
    }
}

Named Pipe Server

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.IO.Pipes;
using System.Threading;
using System.Runtime.Serialization;
using FileTransfer;

namespace ServerNamedPipe
{
    class Program
    {
        static void Main()
        {
            //creating object for file transfer
            using (NamedPipeServerStream pipeServer =
                new NamedPipeServerStream("File Transfer", PipeDirection.Out))
            {
                Console.WriteLine("File Transfer Named Pipe Stream is ready...");
                Console.Write("Waiting for client connection...");//waiting for any client connections
                pipeServer.WaitForConnection();
                Console.WriteLine("Client connected.");
                try
                {
                    string strFile = @"c:\Test\1\Srinivas.txt";

                    //creating FileTransfer Object ans setting the file name
                    TransferFile objTransferFile = new TransferFile() { FileName = new FileInfo(strFile).Name };
                    objTransferFile.FileContent = new MemoryStream();

                    //opening the source file to read bytes
                    using (FileStream fs = File.Open(strFile, FileMode.Open, FileAccess.Read))
                    {
                        byte[] byteBuffer = new byte[1024];
                        int numBytes = fs.Read(byteBuffer, 0, 1024);

                        //writing the bytes to file transfer content stream
                        objTransferFile.FileContent.Write(byteBuffer, 0, 1024);

                        //below code is to write the bytes directly to the pipe stream
                        //pipeServer.Write(byteBuffer, 0, 1024);

                        //Reading each Kbyte and writing to the file content
                        while (numBytes > 0)
                        {
                            numBytes = fs.Read(byteBuffer, 0, numBytes);
                            objTransferFile.FileContent.Write(byteBuffer, 0, 1024);

                            //below code is to write the bytes to pipe stream directly
                            //pipeServer.Write(byteBuffer, 0, numBytes);
                        }

                        //setting the file content (stream) position to begining
                        objTransferFile.FileContent.Seek(0, SeekOrigin.Begin);

                        //serializing the file transfer object to a stream
                        IFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
                        try
                        {
                            //serialzing and writing to pipe stream
                            formatter.Serialize(pipeServer, objTransferFile);
                        }
                        catch (Exception exp)
                        {
                            throw exp;
                        }
                    }
                }
                // Catch the IOException that is raised if the pipe is
                // broken or disconnected.
                catch (IOException e)
                {
                    Console.WriteLine("ERROR: {0}", e.Message);
                }
            }
        }

    }

}

 Named Pipe Client

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.IO.Pipes;
using System.Runtime.Serialization;

namespace ClientNamedPipe
{
    class Program
    {
        static void Main(string[] args)
        {
            //connecting to the known pipe stream server which runs in localhost
            using (NamedPipeClientStream pipeClient =
                new NamedPipeClientStream(".", "File Transfer", PipeDirection.In))
            {


                // Connect to the pipe or wait until the pipe is available.
                Console.Write("Attempting to connect to File Transfer pipe...");
                //time out can also be specified
                pipeClient.Connect();

                Console.WriteLine("Connected to File Transfer pipe.");

                IFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
                //deserializing the pipe stream recieved from server
                FileTransfer.TransferFile objTransferFile = (FileTransfer.TransferFile)formatter.Deserialize(pipeClient);

                //creating the target file with name same as specified in source which comes using
                //file transfer object
                byte[] byteBuffer = new byte[1024];

                using (FileStream fs = new FileStream(@"c:\Test\2\" + objTransferFile.FileName, FileMode.Create, FileAccess.Write))
                {
                    //writing each Kbyte to the target file
                    int numBytes = objTransferFile.FileContent.Read(byteBuffer, 0, 1024);
                    fs.Write(byteBuffer, 0, 1024);
                    while (numBytes > 0)
                    {
                        numBytes = objTransferFile.FileContent.Read(byteBuffer, 0, numBytes);
                        fs.Write(byteBuffer, 0, numBytes);
                    }
                }
                Console.WriteLine("File, Received from server: {0}", objTransferFile.FileName);
            }
            Console.Write("Press Enter to continue...");
            Console.ReadLine();
        }
    }
}



No comments:

Post a Comment