通过命名管道传输xml序列化对象(不带WCF)

时间:2015-09-30 10:03:47

标签: c# pipe xmlserializer named

我想通过简单的命名管道发送特定对象。我认为接收器无法识别两个发送对象之间的切割。在结果中,我得到一个xml序列化错误。这是我的代码:

服务器进程:

using System;
using System.IO;
using System.IO.Pipes;
using System.Threading;
using System.Xml.Serialization;

namespace NamedPipe
{
class ProgramServer
    {
        static void Main(string[] args)
        {
            NamedPipeServerStream server;
            server = new NamedPipeServerStream("PipesOfPiece");

            server.WaitForConnection();

            StreamReader reader = new StreamReader(server);
            StreamWriter writer = new StreamWriter(server);
            Console.WriteLine("Start loop. ");
            Thread.Sleep(1000);

            while (true)
            {
                XmlSerializer receiver = new XmlSerializer(typeof(PayLoad));
                object testobj = receiver.Deserialize(reader);
                Console.WriteLine("Testobject: " + ((PayLoad)(testobj)).name + ((PayLoad)(testobj)).count);
            }
        }
    }
}

客户流程:

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace NamedPipe
{
    class ProgramClient
    {
        static void Main(string[] args)
        {
            //Client
            var client = new NamedPipeClientStream("PipesOfPiece");
            client.Connect();
            StreamReader reader = new StreamReader(client);

            while (true)
            {

                StreamWriter writer = new StreamWriter(client);
                PayLoad test = new PayLoad
                ()
                {
                    name = "Test",
                    count = 42
                };

                XmlSerializer sendSerializer = new XmlSerializer(typeof(PayLoad));
                sendSerializer.Serialize(writer, test);
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

我最近尝试过使用没有WCF的NamedPipes。您可以查看此代码,它可能会给您一些想法。此处,客户端启用了回调功能,因此服务器可以回调客户端。

static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            const string PIPE_NAME = "testPipeName33";
            const string OBJECT_NAME = "test";
            const string CALLBACK_PIPE_NAME = "testPipeName34";
            const string CALLBACK_OBJECT_NAME = "testclient";

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            if ((args.Length == 0 || args[0] == "s"))
            {
                try
                {
                   IPCRegistration.RegisterServer(PIPE_NAME,OBJECT_NAME);
                }
                catch (RemotingException)
                {
                                        remoteObject = IPCRegistration.RegisterClient(typeof(RemoteObject),PIPE_NAME,OBJECT_NAME);
                    remoteObject.OnNewProcessStarted("test");
                    Application.Exit();
                    return;
                }
                MessageBox.Show("Server:" + Process.GetCurrentProcess().Id);
                Process.Start(Application.ExecutablePath, "c");
                Application.Run(new Form1("Server"));

            }
            else
            {
                IsClient = true;
                remoteObject = IPCRegistration.RegisterClient(typeof(RemoteObject), PIPE_NAME, OBJECT_NAME);
                IPCRegistration.RegisterServer(CALLBACK_PIPE_NAME, CALLBACK_OBJECT_NAME); // Here Client will listen on this channel.
                remoteObject.SetOnNewProcessStarted(OnNewProcessStarted,Process.GetCurrentProcess().Id.ToString());
                MessageBox.Show("Client:" + Process.GetCurrentProcess().Id);
                Application.Run(new Form1("Client"));

            }
        }


        static RemoteObject remoteObject;

        static bool IsClient = false;
        static bool OnNewProcessStarted(string commandLine)
        {
            MessageBox.Show("saved:"+commandLine+" Currrent:"+Process.GetCurrentProcess().Id);
            MessageBox.Show("Is Client : " + IsClient);//problem here, IsClient should be true
            return true;
        }
    }

    public delegate bool OnNewProcessStartedDelegate(string text);

    internal class RemoteObject : MarshalByRefObject
    {
        public OnNewProcessStartedDelegate OnNewProcessStartedHandler;
        public string value;
        public bool isCallBack = false;
        const string PIPE_NAME = "testPipeName33";
        const string OBJECT_NAME = "test";
        const string CALLBACK_PIPE_NAME = "testPipeName34";
        const string CALLBACK_OBJECT_NAME = "testclient";
        RemoteObject remoteObject;
        public bool OnNewProcessStarted(string commandLine)
        {
            if (!isCallBack)
            {
                remoteObject.isCallBack = true;
                return remoteObject.OnNewProcessStarted(commandLine);
            }

            if (OnNewProcessStartedHandler != null)
                return OnNewProcessStartedHandler(value);
            return false;
        }



        public void SetOnNewProcessStarted(OnNewProcessStartedDelegate onNewProcessStarted,string value)
        {
            this.value = value;
            OnNewProcessStartedHandler = onNewProcessStarted;
            if (!isCallBack)
            {
                remoteObject = IPCRegistration.RegisterClient(typeof(RemoteObject), CALLBACK_PIPE_NAME, CALLBACK_OBJECT_NAME);
                remoteObject.isCallBack = true;
                remoteObject.SetOnNewProcessStarted(onNewProcessStarted, Process.GetCurrentProcess().Id.ToString());
            }
        }

        public override object InitializeLifetimeService()
        {
            return null;
        }
    }

    internal class IPCRegistration
    {
       public  static RemoteObject RegisterClient(Type remoteObject,string PIPE_NAME,string OBJECT_NAME)
        {
            IpcClientChannel chan = new IpcClientChannel();
            ChannelServices.RegisterChannel(chan, false);

            RemoteObject remoteObjectInstance = (RemoteObject)Activator.GetObject(remoteObject,
                    string.Format("ipc://{0}/{1}", PIPE_NAME, OBJECT_NAME));
            return remoteObjectInstance;
        }
        public static void RegisterServer(string pipeName, string objectName)
        {
            BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
            serverProvider.TypeFilterLevel = TypeFilterLevel.Full;

            IpcServerChannel chan = new IpcServerChannel("", pipeName, serverProvider);
            ChannelServices.RegisterChannel(chan, false);

            RemotingServices.Marshal(new RemoteObject(), objectName);
        }
    }