【发布时间】:2017-06-15 06:50:48
【问题描述】:
我正在开发一个 .NET 应用程序,其中服务器通过 TCP/IP 将 JPG 压缩图像从网络摄像头发送到客户端。对于序列化/反序列化,我使用BinaryFormatter 类。在我的台式计算机(客户端/Windows 10)和我的笔记本电脑(服务器/Windows 10)之间进行测试时,从长远来看,一切正常。使用 LattePanda(服务器/Windows 7)时,运行大约 3-5 分钟后出现以下错误(每秒发送/接收 30 帧):
An unhandled exception of type 'System.Runtime.Serialization.SerializationException' occurred in mscorlib.dll
Additional information: The input stream is not a valid binary format. The starting contents (in bytes) are: 00-00-00-01-00-00-00-FF-FF-FF-FF-01-00-00-00-00-00 ...
这是来自服务器代码的 sn-p:
private void distribute(Camera camera, Mat frame) {
if(clientSockets!=null) {
if(clientSockets.Count > 0) {
if(camera.Streaming) {
// compress and encapsulate raw image with jpg algorithm
CameraImage packet = new CameraImage(camera.Id, frame, camera.CodecInfo, camera.EncoderParams);
packet.SystemId = Program.Controller.Identity.Id;
packet.SequenceNumber = curSeqNum;
byte[] content;
using(MemoryStream ms = new MemoryStream()) {
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, packet);
content = ms.ToArray();
}
byte[] payload = new byte[content.Length+4];
// prefix with packet length
Array.Copy(BitConverter.GetBytes(content.Length), 0, payload, 0, 4);
// append payload after length header
Array.Copy(content, 0, payload, 4, content.Length);
// distribute to connected clients
this.distribute(payload);
}
}
}
}
private void distribute(byte[] bytes) {
if(Program.Launched) {
lock(syncobj) {
// distribute to connected clients
for(int i=clientSockets.Count-1; i>=0; i--) {
try {
clientSockets[i].Send(bytes, bytes.Length, SocketFlags.None);
} catch(SocketException) {
clientSockets.RemoveAt(i);
}
}
}
}
}
这是来自客户端代码的 sn-p:
private void receive() {
try {
while(running) {
if((available = clientSocket.Receive(buffer, 4, SocketFlags.None)) > 0) {
// receive bytes from tcp stream
int offset = 0;
int bytesToRead = BitConverter.ToInt32(buffer, 0);
byte[] data = new byte[bytesToRead];
while(bytesToRead > 0) {
int bytesReceived = clientSocket.Receive(data, offset, bytesToRead, SocketFlags.None);
offset += bytesReceived;
bytesToRead -= bytesReceived;
}
// deserialize byte array to network packet
NetworkPacket packet = null;
using(MemoryStream ms = new MemoryStream(data)) {
BinaryFormatter bf = new BinaryFormatter();
packet = (NetworkPacket)bf.Deserialize(ms);
}
// deliver network packet to listeners
if(packet!=null) {
this.onNetworkPacketReceived?.Invoke(packet);
}
// update network statistics
NetworkStatistics.getInstance().TotalBytesRtpIn += data.Length;
}
}
} catch(SocketException ex) {
onNetworkClientDisconnected?.Invoke(agent.SystemId);
} catch(ObjectDisposedException ex) {
onNetworkClientDisconnected?.Invoke(agent.SystemId);
} catch(ThreadAbortException ex) {
// allows your thread to terminate gracefully
if(ex!=null) Thread.ResetAbort();
}
}
任何想法为什么我只在一台机器上而不是在另一台机器上得到SerializationException?安装了不同的mscorlib.dll 库?如何查看相关 (?) 库的版本?
【问题讨论】:
-
任何机会
clientSocket.Receive(buffer, 4, SocketFlags.None))返回值< 4但> 0?此外,BinaryFormatter仅用于同一台机器上进程之间的 IPC,不适用于持久存储或网络通信。这是一个非常脆弱的协议。我强烈建议您切换到不同的,例如ProtoBuf-net,它旨在处理机器之间的差异。 -
最好不要搜索此错误的来源,而只是切换出 BinaryFormatter。不适合这个任务。
-
我的钱将完全按照@Scott 所说的那样进行——第一次阅读是不安全的。我也是删除 BinaryFormatter 想法的忠实拥护者,并且是公认的建议库的有偏见的倡导者....咳
-
@dbc 除了可疑的第一次读取:是的,它们是 - 它们具有有效负载的长度前缀。它的实施效率不是特别高,但是:修复第一次阅读,理论上它应该可以正常工作。
-
@salocinx 好吧,如果你改变主意...我总是愿意帮助人们。
标签: c# binaryformatter