Inter-Process Communication with named pipes, Part 02: transfer an object

In the previous article of this series you have seen how to use named pipes to transfer data between two processes. In the example application of this previous article only byte data was send between the processes. Within this article I want to show you a possibility to use more complex data.

 
Serialization

To transfer an object between the two processes I want to use the .NET serialization features. The idea is to serialize the data class into a string with XML format. Afterwards this string is send from server to child process by using an anonymous pipe. The child will deserialize the received XML data and create the object instance of the data class.

 
Data object

To test the serialization feature I want to use the following data class. This data class has two string values and two lists with values. Furthermore I have added the ToString function which allows me to show the content of the data class within the demo console application.

public class MyClass
{
    public string MyValueA { get; set; }
    public string MyValueB { get; set; }
    public List<Int32> MyValuesC { get; set; }
    public List<string> MyValuesD { get; set; }

    public override string ToString()
    {
        StringBuilder data = new StringBuilder();

        data.Append("A = ");
        data.Append(MyValueA);
        data.Append(" | ");

        data.Append("B = ");
        data.Append(MyValueB);
        data.Append(" | ");

        data.Append("C = ");
        data.Append("[");
        if (MyValuesC != null)
        {
            foreach (int value in MyValuesC)
            {
                data.Append(value);
                data.Append(",");
            }
            data.Remove(data.Length - 1, 1);
        }
        data.Append("]");
        data.Append(" | ");

        data.Append("D = ");
        data.Append("[");
        if (MyValuesC != null)
        {
            foreach (string value in MyValuesD)
            {
                data.Append(value);
                data.Append(",");
            }
            data.Remove(data.Length - 1, 1);
        }
        data.Append("]");

        return data.ToString();
    }
}

 
Server process

The server process will send the data class to the child process. Therefore I have created a serialization function. This function is based on the XmlSerializer class and will convert the data object into a string with XML format.

public static string SerializeToXml(MyClass data)
{
    string xmlData = null;

    StringWriter stringWriter = null;

    XmlSerializer serializer = new XmlSerializer(data.GetType());
    stringWriter = new StringWriter();
    serializer.Serialize(stringWriter, data);

    xmlData = stringWriter.ToString().Replace(Environment.NewLine, " ");

    stringWriter.Close();

    return xmlData;
}

 
The console application is based on the example of the previous article of this series. Only minor adaptations are done to create, serialize and show the data object.

static void Main(string[] args)
{
    //create pipe
    var pipe = new NamedPipeServerStream("MyPipe", PipeDirection.InOut, 1);

    //wait until client connects
    pipe.WaitForConnection();
    Console.WriteLine("Client is connected");

    //create test data
    MyClass data = new MyClass();
    data.MyValueA = "foobar";
    data.MyValueB = null;
    data.MyValuesC = new List<Int32>() { 1, 2, 3 };
    data.MyValuesD = new List<string>() { "foo", "bar" };

    string xmlData = SerializeToXml(data);

    //write and read data
    try
    {
        //write data
        Console.WriteLine("Parent send: " + data);
                
        StreamWriter writer = new StreamWriter(pipe);
        writer.WriteLine(xmlData);
        writer.Flush();
                
        //read data
        int dataReceive = pipe.ReadByte();
        Console.WriteLine("Parent receive: " + dataReceive.ToString());
    }
    //catch exception on broken or disconnected pipe
    catch (IOException exception)
    {
        Console.WriteLine("Error: {0}", exception.Message);
    }
            
    //close pipe
    pipe.Close();

    Console.ReadKey();
}

 
Child process

The child process will receive the XML data and convert it back into an object instance. Therefore I have implemented a deserialization function.

public static MyClass DeserializeFromXML(string xmlData)
{
    MyClass data = null;

    StringReader stringReader = null;

    XmlSerializer deserializer = new XmlSerializer(typeof(MyClass));
    stringReader = new StringReader(xmlData);
    data = (MyClass)deserializer.Deserialize(stringReader);            

    return data;
}

 
Also the child application is nearly the same as in the first article of this series. Only the features to handle the data class where added. The data will read with the ReadLine function. This function will return if data is received. To create an easy example the whole XML data will send in one line and therefore the client has to read only this one line. In a more complex communication scenario you may use own threads to send and receive data.

static void Main(string[] args)
{
    //connect
    var pipe = new NamedPipeClientStream("127.0.0.1", "MyPipe", 
        PipeDirection.InOut, PipeOptions.None, TokenImpersonationLevel.Impersonation);

    pipe.Connect();
    Console.WriteLine("Connected with server");

    //read data
    MyClass myClass;
    StreamReader reader = new StreamReader(pipe);
            
    string xmlData = "";

    xmlData = reader.ReadLine();
            
    myClass = DeserializeFromXML(xmlData);
    Console.WriteLine("Client receive: " + myClass);

    //write data
    byte dataSend = 24;
    pipe.WriteByte(dataSend);
    Console.WriteLine("Client send: " + dataSend.ToString());  

    //close pipe
    pipe.Close();

    Console.ReadKey();
}

 
Summary

By using serialization features it is possible to transfer complex data objects over pipes. The combination of named pipes and serialization will allow you to create a flexible and easy to use solution for data exchange between two processes.

Werbung
Dieser Beitrag wurde unter .NET, C# abgelegt und mit , verschlagwortet. Setze ein Lesezeichen auf den Permalink.

Eine Antwort zu Inter-Process Communication with named pipes, Part 02: transfer an object

  1. Wednesday schreibt:

    Call me wind because I am ablotulesy blown away.

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit deinem WordPress.com-Konto. Abmelden /  Ändern )

Facebook-Foto

Du kommentierst mit deinem Facebook-Konto. Abmelden /  Ändern )

Verbinde mit %s