如果这是一个愚蠢的问题,我道歉,我几乎没有睡觉。
我在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;
}