序列化手动编写的代码

Serializing a manually written code

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

这是'should'被序列化的客户端

 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;


        }

    }

谢谢。

序列化一段数据时需要遵循一些规则。 将数据转换为字节很容易,但要考虑如何在另一端重构数据。假设服务器不知道您发送的内容。

在您的序列化器中,您只需将几个字符串转换为字节[] 并将其发送过来。示例:

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

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

服务器收到:"abcdefghijk"

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

有办法解决这个问题:

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

    一样微不足道

    字符串 x = data.Substring(0, 6) 字符串 y = data.Substring(6, 5)

  2. 在字段之间使用分隔符。如果您熟悉 cvs,',' 将字段分开。然而,这有它的缺点,如何处理字符串中某处的','?发送过来的数据类似于“abcdef,ghijk

  3. 在字段内容之前发送每个字段的大小。 一个天真的方法只是为了澄清:字符串 x 将作为 '6abcdef' 发送,y 作为 '5ghijk'

手工完成所有这些事情真的很麻烦,只有在真正需要时我才会考虑这样做。

我会求助于在这个问题上做得很好的现有框架:

Json.net

protobuf ported by Jon skeet

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

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);