-1

我试图将一些对象从服务器发送到客户端。我的问题是,当我只发送 1 个对象时,一切正常。但是在我添加另一个对象时,会引发异常-“二进制流不包含有效的二进制头”或“没有对象映射(随机数)”。我的想法是反序列化不了解流的开始/结束位置,我希望你们能在这里帮助我。

这是我的反序列化代码:

public void Listen()
        {
            try
            {
                bool offline = true;
                Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
                    new Action(() => offline = Offline));
                while (!offline)
                {
                    TcpObject tcpObject = new TcpObject();
                    IFormatter formatter = new BinaryFormatter();
                    tcpObject = (TcpObject)formatter.Deserialize(serverStream);

                    if (tcpObject.Command == Command.Transfer)
                    {
                        SentAntenna sentAntenna = (SentAntenna)tcpObject.Object;

                        int idx = 0;
                        foreach (string name in SharedProperties.AntennaNames)
                        {
                            if (name == sentAntenna.Name)
                                break;
                            idx++;
                        }

                        if (idx < 9)
                        {
                            PointCollection pointCollection = new PointCollection();
                            foreach (Frequency f in sentAntenna.Frequencies)
                                pointCollection.Add(new Point(f.Channel, f.Intensity));

                            SharedProperties.AntennaPoints[idx] = pointCollection;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message); // raise an event
            }
        }

序列化代码:

case Command.Transfer:
                            Console.WriteLine("Transfering");
                            Thread transfer = new Thread(new ThreadStart(delegate
                            {
                                try
                                {
                                    string aName = tcpObject.Object.ToString();
                                    int indx = 0;
                                    foreach (string name in names)
                                    {
                                        if (name == aName)
                                            break;
                                        indx++;
                                    }

                                    if (indx < 9)
                                    {
                                        while (true) // need to kill when the father thread terminates
                                        {
                                            if (antennas[indx].Frequencies != null)
                                            {
                                                lock (antennas[indx].Frequencies)
                                                {
                                                    TcpObject sendTcpObject = new TcpObject();
                                                    sendTcpObject.Command = Command.Transfer;
                                                    SentAntenna sa = new SentAntenna(antennas[indx].Frequencies, aName);
                                                    sendTcpObject.Object = sa;
                                                    formatter.Serialize(networkStream, sendTcpObject);
                                                }
                                            }
                                        }
                                    }
                                }
                                catch (Exception ex) { Console.WriteLine(ex); }
                            }));
                            transfer.Start();
                            break;
4

2 回答 2

1

有趣的。在您的序列化代码中没有什么特别奇怪的地方,而且我过去曾看到人们对多个对象使用香草连接,尽管我实际上一直建议不要这样做,因为 BinaryFormatter 没有明确声称这种情况是可以的。但是:如果不是,我唯一能建议的就是实现你自己的框架;所以你的写代码变成:

  • 序列化为空的 MemoryStream
  • 记下长度并将长度写入 NetworkStream,例如作为简单的固定宽度 32 位网络字节顺序整数
  • 将有效负载从 MemoryStream 写入 NetworkStream
  • 冲洗,重复

读取的代码变为:

  • 准确读取 4 个字节并计算长度
  • 将那么多字节缓冲到 MemoryStream 中
  • 从 NetworkStream 反序列化

(注意在这两种情况下将 MemoryStream 的位置在写入和读取之间设置回 0)

如果您想在读取时避免使用缓冲区,您还可以实现一个限制长度的 Stream 子类,这更复杂。

于 2012-12-09T18:13:50.100 回答
0

显然我想出了一个非常简单的解决方案。我只是确保只允许 1 个线程同时传输数据,所以我更改了这行代码:

formatter.Serialize(networkStream, sendTcpObject);

到这些代码行:

if (!transfering) // making sure only 1 thread is transfering data
{
    transfering = true;
    formatter.Serialize(networkStream, sendTcpObject);
    transfering = false;
}
于 2012-12-11T14:37:18.530 回答