二进制流'0'不包含有效的BinaryHeader。随机发生

时间:2014-07-22 11:44:59

标签: c# tcp firebird

我正在处理处理firebird数据库请求的c#windows服务。当我尝试在客户端应用程序上反序列化对象时,我的问题发生在随机时刻(有时在5分钟之后,有时仅在4次调用数据库之后)。它仅在特定位置发生(在54字节数组中停止在第18个字节处)。其余时间函数返回正确的结果。


我使用此功能序列化单个对象

public byte[] ObjectToByteArray(Object obj)
{
    if (obj == null)
        return null;
    MemoryStream fs = new MemoryStream();
    BinaryFormatter formatter = new BinaryFormatter();
    formatter.Serialize(fs, obj);
    fs.Seek(0, SeekOrigin.Begin);
    byte[] rval = fs.ToArray();
    fs.Close();
    return rval;
}

我没有序列化任何自定义类,只有字符串和数字类型(firebird api将它们作为对象返回)。 我用它来反序列化:

public object ByteArrayToObject(Byte[] Buffer)
{
    BinaryFormatter formatter = new BinaryFormatter();
    MemoryStream stream = new MemoryStream(Buffer);
    stream.Position = 0;
    object rval = formatter.Deserialize(stream); <--- this thing drives me nuts.
    stream.Close();
    return rval;
}

和客户端应用程序中的主要功能。抱歉丑陋的代码,

    public List<object[]> ByteToList(byte[] data, int[] pomocnicza)
    {
        //pomocnicza table contains size of (original) particular column of list in bytes
        int size_row = 0;
        foreach (int i in pomocnicza)
        { size_row += i; }
        List<object[]> result = new List<object[]>();
        int iterator = 0;
        for (int i = 0; i < data.Length / size_row ; i++)
        {
            object[] zxc = new object[3];
            int l = pomocnicza.Length/4;
            for (int j = 0; j < l; j++)
            {
                byte[] tmp = new byte[pomocnicza[j*4]];
                System.Array.Copy(data, iterator, tmp, 0, pomocnicza[j*4]);
                object ffs = ByteArrayToObject(tmp);
                zxc[j] = ffs;
                iterator += pomocnicza[j*4];
            }
            result.Add(zxc);
        }
        return result;
    }

令我感到困惑的是,它在大多数情况下有效,但不可避免地会导致错误。它随机发生的事情使得难以定位。请帮忙。


@EDIT 这就是我阅读输入的方式:

    public List<object[]> RetrieveSelectData(FbConnection dbConn, string SQLCommand)
    {
        using (var command = dbConn.CreateCommand())
        {
            command.CommandText = SQLCommand;
            using (var reader = command.ExecuteReader())
            {
                var rows = new List<object[]>();
                while (reader.Read())
                {
                    var columns = new object[reader.FieldCount];
                    reader.GetValues(columns);
                    rows.Add(columns);
                }
                return rows;
            }
        }
    }

然后使用此函数序列化

    public byte[] ListToByte(List<object[]> lista, out int[] rozmiary)
    {
        int size= 0;
        rozmiary = new int[lista[0].Length];
        for (int i = 0; i < lista[0].Length; i++)
        {
            byte[] test = this.ObjectToByteArray(lista[0][i]);
            size+= test.Length;
            rozmiary[i] = test.Length;
        }
        size*= lista.Count;
        byte[] result = new byte[size];
        int index = 0;
        for (int i = 0; i < lista.Count; i++)
        {
            for (int j = 0; j < lista[i].Length; j++)
            {
                byte[] tmp = this.ObjectToByteArray(lista[i][j]);                  
                tmp.CopyTo(result, index);
                index += tmp.Length;
            }
        }
        return result;
    }

2 个答案:

答案 0 :(得分:1)

如果您使用上述反序列化方法&amp;从客户端流或其他流获取流时也调用它们....跳过它。尝试直接使用格式化程序的那些流。如下:

NetworkStream clientStream = client.GetStream();
Object src = (Object)formatter.Deserialize(clientStream);

答案 1 :(得分:0)

我找到了这个bug。上面的代码工作正常,但在某些情况下(!)需要关注编码,所以请随意使用它。 问题出现在程序的另一部分,我错误输入并发送4个字节但客户端应用程序被告知接收8,因此在大多数情况下,它用零填充它,但有时它从下一个数据包中得到它。

@Marc Gravell和他的博客让我一遍又一遍地寻找源头。