协议缓冲区 - 不一致的序列化?

时间:2013-06-08 05:59:57

标签: c# c++ serialization buffer protocols

如果这是一个愚蠢的问题,我道歉,我几乎没有睡觉。

我在C ++中序列化协议缓冲区消息,并通过TCP连接将其发送到C#客户端。一切都在大约75%的时间内起作用,但是,大约25%的时间,我得到无效的序列化异常。

经过一番探索之后,我发现有效消息中的字节数组与无效消息不同。看起来一直是同一个字节,这是错误的。

我可以在必要时发布代码,但我在这里遗漏了什么吗?为什么C ++服务器每次都不会将对象序列化相同? (顺便说一句,我硬编码了一个对象来测试它。确保字段没有变化。)

从客户端的角度来看,这是通过套接字发送后的字节数组。

8 162 1 18 21 84 87 32 86 101 110 100 105 110 103 32 68 101 109 111 32 83 116 111 114 101 24 176 32 132 131 186 141 5 40 2 48 42 56 2 - bad serialization

8 162 1 18 21 84 87 32 86 101 110 100 105 110 103 32 68 101 109 111 32 83 116 111 114 101 24   7 32 132 131 186 141 5 40 2 48 42 56 2 - good serialization

8 162 1 18 21 84 87 32 86 101 110 100 105 110 103 32 68 101 109 111 32 83 116 111 114 101 24 128 32 132 131 186 141 5 40 2 48 42 56 2 - bad serialization

8 162 1 18 21 84 87 32 86 101 110 100 105 110 103 32 68 101 109 111 32 83 116 111 114 101 24 216 32 132 131 186 141 5 40 2 48 42 56 2 - bad serialization

8 162 1 18 21 84 87 32 86 101 110 100 105 110 103 32 68 101 109 111 32 83 116 111 114 101 24   0 32 132 131 186 141 5 40 2 48 42 56 2 - good serialization

8 162 1 18 21 84 87 32 86 101 110 100 105 110 103 32 68 101 109 111 32 83 116 111 114 101 24 255 32 132 131 186 141 5 40 2 48 42 56 2 - bad serialization

请注意,结尾的第13个字节是不同的?我还添加了成功序列化的那些。感谢。

更新 - 我发布了我的C#客户端代码,因为这个问题最有可能就是这个问题。我还包装了生成的proto对象,所以你必须接受我的话,我的序列化功能正常工作。 (我100%肯定他们是。)

 private List<byte> LockNetworkStream(ref System.IO.Stream clientStream, byte[] data)
        {
            List<byte> completeMessage = new List<byte>();

            try
            {
                lock (clientStream)
                {
                    byte[] bufferLength = BitConverter.GetBytes(data.Length);
                    clientStream.ReadTimeout = 10000;

                    clientStream.Write(bufferLength, 0, bufferLength.Length);
                    clientStream.Flush();

                    clientStream.Write(data, 0, data.Length);
                    clientStream.Flush();

                    byte[] messageLength = new byte[4];
                    int bytesRead = 0;

                    bytesRead = clientStream.Read(messageLength, 0, 4);
                    int messageSize = BitConverter.ToInt32(messageLength, 0);
                    if (messageSize > 0)
                    {
                        int totalBytesRead = 0;
                        byte[] message = new byte[messageSize];                        
                        while (totalBytesRead < messageSize)
                        {
                            bytesRead = clientStream.Read(message, 0, messageSize - totalBytesRead);
                            if (bytesRead > 0)
                            {
                                byte[] temp = new byte[bytesRead];
                                for (int i = 0; i < bytesRead; i++)
                                {
                                    temp[i] = message[i];
                                }

                                completeMessage.AddRange(temp);
                                totalBytesRead += bytesRead;
                            }
                            else
                            {
                                break;
                            }
                        }

                        clientStream.Flush();
                    }
                }  
            }
            catch (StokedTcpException ex)
            {
                throw ex;
            }
            catch (InvalidOperationException ex)
            {
                if (reconnectAttempts < 3)
                {
                    Reconnect();
                    return LockNetworkStream(ref clientStream, data);   
                }
                else
                {
                    throw new Exception("Unable to connect.  Please check your internet connection or firewall config");
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return completeMessage;
        }

        public byte[] Communicate(byte[] data, ref TcpClient client)
        {
            byte[] bufferLength = BitConverter.GetBytes(data.Length);
            System.IO.Stream clientStream = null;
            lock (client)
            {
                clientStream = client.GetStream();
            }            

            List<byte> completeMessage = LockNetworkStream(ref clientStream, data);

            ServerFunctionResponse response = null;
            try
            {
                response = ServerFunctionResponse.Deserialize(completeMessage.ToArray());
                deserializeAttempts = 0;
            }
            catch (Exception ex)
            {

                throw new Exception("Unable to deserialize server response: " + ex.Message);
            }

            if (response.IsException)
            {
                StokedTcpException exception = StokedTcpException.Deserialize(response.Data);
                throw exception;
            }

            return response.Data;            
        }

0 个答案:

没有答案