如何使用命名管道发送多个对象?

时间:2014-10-21 14:29:24

标签: c# serialization stream deserialization named-pipes

我正在尝试使用命名管道从服务器向客户端发送4个参数 - 一个整数,一个bool和两个字符串。 我尝试了不同的方法,但仍未成功。 第一种方式 - 我只是将所有参数转换为字符串并尝试发送,但在客户端我收到所有参数为null:

服务器代码:

   static void StartServer()
        {
            var server = new NamedPipeServerStream("PipesEnroll", PipeDirection.InOut);

                while (true)
                {
                    server.WaitForConnection();
                    StreamWriter writer = new StreamWriter(server);
                    string terminalTemplate;
                    string matcherTemplate;
                    int mathVersionNumber = 9;
                    int numberFingers;
                    bool isOk = Enroll.EnrollWithoutWCF(retrievedList, mathVersionNumber, out terminalTemplate, out matcherTemplate, out numberFingers);

                    writer.WriteLine(isOk.ToString());
                    writer.WriteLine(terminalTemplate);
                    writer.WriteLine(matcherTemplate);
                    writer.WriteLine(numberFingers.ToString());
                    writer.Flush();

                    server.Disconnect();
           }

客户代码:

                   using (var client = new NamedPipeClientStream(".", "PipesEnroll", PipeDirection.InOut))
                    {
                        client.Connect();
                        StreamReader reader = new StreamReader(client);

                          bool isOK = Convert.ToBoolean(reader.ReadLine());
                          string terminalTemplate = reader.ReadLine();
                          string matcherTemplate = reader.ReadLine();
                          int numberFingers = Convert.ToInt32(reader.ReadLine());

                    }

我做的第二种方法是创建字符串列表并在服务器上对其进行序列化,在客户端使用BinaryFormatter进行反序列化,但是遇到了这个异常:“System.Runtime.Serialization.SerializationException:在解析完成之前遇到Stream的结束”

服务器代码:

   var server = new NamedPipeServerStream("PipesEnroll", PipeDirection.InOut);
while (true)
{
        server.WaitForConnection();
        StreamWriter writer = new StreamWriter(server);   
List<string> sendList = new List<string>();
  sendList.Add(isOk.ToString());
  sendList.Add(terminalTemplate);
  sendList.Add(matcherTemplate);
  sendList.Add(numberFingers.ToString());
  BinaryFormatter formatterSerialize = new BinaryFormatter();
  formatterSerialize.Serialize(writer.BaseStream, sendList);
  writer.Flush();
  server.Disconnect();
 }

客户代码:

using (var client = new NamedPipeClientStream(".", "PipesEnroll", PipeDirection.InOut))
          {
             client.Connect();
             StreamReader reader = new StreamReader(client);   
 BinaryFormatter formatterDeserialize = new BinaryFormatter();
    List<string> retrievedList =  (List<string>) formatterDeserialize.Deserialize(reader.BaseStream);
}

1 个答案:

答案 0 :(得分:3)

最后,我已经能够使用xml序列化和特定数据协议来执行此操作,以便读取和写入字符串。

具有我们需要从服务器传递到客户端的乘法数据的类,实现了两个用于序列化/反序列化到xml中的方法:

[Serializable]
public class ServerData
{
    public bool Result { get; set; }

    public int Int1 { get; set; }

    public string Str1 { get; set; }

    public string Str2 { get; set; }

    public static string Serialize(ServerData dto)
    {
        //Add an empty namespace and empty value
        XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
        ns.Add("", "");
        XmlSerializer ser = new XmlSerializer(typeof(ServerData));
        using (StringWriter textWriter = new StringWriter())
        {
            ser.Serialize(textWriter, dto, ns);
            return textWriter.ToString();
        }
    }

    public static ServerData Deserialize(string xml)
    {
        XmlSerializer ser = new XmlSerializer(typeof(ServerData));
        using (var reader = new StringReader(xml))
        {
            return (ServerData)ser.Deserialize(reader);
        }
    }
}

类助手,定义用于读写字符串的数据协议:

public class StreamString
{
    private Stream ioStream;
    private UnicodeEncoding streamEncoding;

    public StreamString(Stream ioStream)
    {
        this.ioStream = ioStream;
        streamEncoding = new UnicodeEncoding();
    }

    public string ReadString()
    {
        byte[] strSizeArr = new byte[sizeof(int)];
        ioStream.Read(strSizeArr, 0, sizeof(int));
        int strSize = BitConverter.ToInt32(strSizeArr, 0);
        byte[] inBuffer = new byte[strSize];
        ioStream.Read(inBuffer, 0, strSize);
        return streamEncoding.GetString(inBuffer);
    }

    public int WriteString(string outString)
    {
        byte[] outBuffer = streamEncoding.GetBytes(outString);
        byte[] strSize = BitConverter.GetBytes(outBuffer.Length);
        ioStream.Write(strSize, 0, strSize.Length);
        ioStream.Write(outBuffer, 0, outBuffer.Length);
        ioStream.Flush();
        return outBuffer.Length + 2;
    }
}

服务器代码:

[STAThread]
static void Main(string[] args)
{

    Thread serverThread = new Thread(ServerThread);
    serverThread.Priority = ThreadPriority.Highest;
    serverThread.Start();
    serverThread.Join();
}

static void ServerThread()
{
    using (var server = new NamedPipeServerStream("PipesEnroll", PipeDirection.InOut, 1))
    {
        server.WaitForConnection();
        var ss = new StreamString(server);

        string terminalTemplate;
        string matcherTemplate;
        const int mathVersionNumber = 9;
        int numberFingers;
        bool isOk = Enroll.EnrollWithoutWCF(images, mathVersionNumber, out terminalTemplate, out matcherTemplate,
            out numberFingers);
        var dtoSend = new ServerData();
        dtoSend.Result = isOk;
        dtoSend.Int1 = numberFingers;
        dtoSend.Str1 = terminalTemplate;
        dtoSend.Str2 = matcherTemplate;
        var xmlSend = ServerData.Serialize(dtoSend);
        ss.WriteString(xmlSend);
        server.WaitForPipeDrain();
        server.Close();
    }
}

客户代码:

 using (
   var client = new NamedPipeClientStream(".", "PipesEnroll", PipeDirection.InOut,
                PipeOptions.None, TokenImpersonationLevel.Impersonation))
                {
                 client.Connect();
                 var ss = new StreamString(client);
                 string xmlReceive = ss.ReadString();
                 var dtoReceived = ServerData.Deserialize(xmlReceive);
                 bool isOK = dtoReceived.Result;
                string terminalTemplate = dtoReceived.Str1;
                 string matcherTemplate = dtoReceived.Str2;
                 int numberFingers = dtoReceived.Int1;
    }
}