序列化手动编写的代码

时间:2015-09-19 12:04:01

标签: c# .net winforms serialization client-server

我在从客户端接收文件时遇到问题。有人建议我应该使用二进制序列化来发送和接收流中的消息。你能告诉我如何序列化这个想法吗?我不久前刚学会了序列化,所以我对如何将它与我的程序联系起来很困惑。

这是'应该'序列化

的客户端
 public void sendthedata()
        {
            if (!_timer.Enabled) // If timer is not running send data and start refresh interval
            {
                SendData();
                _timer.Enabled = true;
            }
            else // Stop timer to prevent further refreshing
            {
                _timer.Enabled = false;
            }
        }
        private List<int> listedProcesses = new List<int>();
        private void SendData()
        {
            String processID = "";
            String processName = "";
            String processPath = "";
            String processFileName = "";
            String processMachinename = "";

            listBox1.BeginUpdate();
            try
            {   
                piis = GetAllProcessInfos();
                for (int i = 0; i < piis.Count; i++)
                {
                    try
                    {
                        if (!listedProcesses.Contains(piis[i].Id)) //placed this on a list to avoid redundancy
                        {
                            listedProcesses.Add(piis[i].Id);
                            processID = piis[i].Id.ToString();
                            processName = piis[i].Name.ToString();
                            processPath = piis[i].Path.ToString();
                            processFileName = piis[i].FileName.ToString();
                            processMachinename = piis[i].Machinename.ToString();
                            output.Text += "\n\nSENT DATA : \n\t" + processFileName + "\n\t" + processMachinename + "\n\t" + processID + "\n\t" + processName + "\n\t" + processPath + "\n";
                        }

                    }
                    catch (Exception ex)
                    {
                        wait.Abort();
                        output.Text += "Error..... " + ex.StackTrace;

                    }

                    NetworkStream ns = tcpclnt.GetStream();
                    String data = "";
                    data = "--++" + processFileName + " " +  processMachinename + " "  + processID + " " + processPath;
                    if (ns.CanWrite)
                    {
                        byte[] bf = new ASCIIEncoding().GetBytes(data);
                        ns.Write(bf, 0, bf.Length);
                        ns.Flush();
                    }
                }
            }
            finally
            {
                listBox1.EndUpdate();
            } 
        }

在服务器中反序列化

private void recieveData()
    {
        NetworkStream nStream = tcpClient.GetStream();
        ASCIIEncoding ascii = null;
        while (!stopRecieving)
        {
            if (nStream.CanRead)
            {
                byte[] buffer = new byte[1024];
                nStream.Read(buffer, 0, buffer.Length);
                ascii = new ASCIIEncoding();
                recvDt = ascii.GetString(buffer);
                /*Received message checks if it has +@@+ then the ip is disconnected*/
                bool f = false;
                f = recvDt.Contains("+@@+");
                if (f)
                {
                    string d = "+@@+";
                    recvDt = recvDt.TrimStart(d.ToCharArray());
                    clientDis();
                    stopRecieving = true;
                }

                //else if (recvDt.Contains("^^"))
                //{
                //    new Transmit_File().transfer_file(file, ipselected);
                //}
                /* ++-- shutsdown/restrt/logoff/abort*/
                else if (recvDt.Contains("++--"))
                {
                    string d = "++--";
                    recvDt = recvDt.TrimStart(d.ToCharArray());
                    this.Invoke(new rcvData(addToOutput));
                    clientDis();
                }
                /*--++ Normal msg*/
                else if (recvDt.Contains("--++"))
                {
                    string d = "--++";
                    recvDt = recvDt.TrimStart(d.ToCharArray());
                    this.Invoke(new rcvData(addToOutput));

                }
            }
            Thread.Sleep(1000);
        }

    }

    public void addToOutput()
    {
        if (recvDt != null && recvDt != "")
        {

            output.Text += "\n Received Data : " + recvDt;
            recvDt = null;


        }

    }

谢谢。

1 个答案:

答案 0 :(得分:2)

序列化一段数据时需遵循几条规则。 将数据转换为字节很容易,但考虑如何在另一侧重建数据。假设服务器无法了解您所发送的内容。

在您的序列化程序中,您只需将几个字符串转换为byte []并将其发送出去。例如:

string x = "abcdef";
string y = "ghijk";

var bytes = Encoding.Ascii.GetBytes(x + y);

服务器收到:"abcdefghijk";

服务器是否可以确定并重建字符串x和y? 由于服务器不知道x和y的长度:否。

有办法解决这个问题:

  1. 使用固定长度字段。在我的例子中,x应始终为6个字符,y应始终为5个字符。然后,服务器上的解码变得像

    一样简单

    string x = data.Substring(0,6) string y = data.Substring(6,5)

  2. 在字段之间使用分隔符。如果你熟悉cvs,&#39;,&#39;拆分字段。然而,这有它的缺点,如何处理,&#39;字符串中的某个地方?发送的数据类似于&#34; abcdef,ghijk&#34;

  3. 在字段内容之前发送每个字段的大小。 一个简单的方法只是澄清:字符串x将被发送为&#39; 6abcdef&#39;和y作为&#39; 5ghijk&#39;

  4. 手工完成所有这些事情会变得非常毛茸茸,只有在真正需要的时候才能考虑。

    我会诉诸现有的框架,在这个问题上做得很好:

    Json.net

    protobuf ported by Jon skeet

    在这种情况下,我首先创建一个类来定义发送到服务器的数据而不是一堆字符串:

    class ProcessInfo{
        public string ProcessID {get;set;}
        public string ProcessName {get;set;}
        public string ProcessPath {get;set;}
        public string ProcessFileName {get;set;}
        public string ProcessMachinename {get;set;}
    };
    

    使用Json序列化:

    var procinfo = new ProcessInfo{
                       ProcessId = "1",
                       ...
                   };
    var serialised = JsonConvert.SerializeObject(procinfo);
    var bytes = Encoding.Utf8.GetBytes(serialised);
    ns.Write(bytes, 0, bytes.Length);
    

    只需通过以下方式在服务器上恢复它:

    var procInfo = JsonConvert.DeserializeObject<ProcessInfo>(json);