我正在开发一个.NET应用程序,在这个应用程序中,服务器通过TCP/IP将JPG压缩图像从摄像头发送到客户端。对于序列化/反序列化,我使用BinaryFormatter类。在我的桌面计算机(client/Windows 10)和我的笔记本电脑(服务器/Windows 10)之间进行测试时,从长远来看,一切正常。当使用LattePanda (server/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 ...下面是服务器代码的一个片段:
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);
}
}
}
}
}下面是客户端代码的一个片段:
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库?如何检查相关版本(?)图书馆?
发布于 2017-06-14 22:38:51
下面是一个经过调整的your answer版本。现在,如果是clientSocket.Available < 4和running == true,则有一个空的while(true) { }循环。这将占用100%的cpu核心做什么有用的工作。
不要循环直到系统I/O缓冲区中有4个字节,而是使用与消息的有效负载相同的循环,并将其加载到字节数组中作为标题。(我还简化了将有效负载数据读取到异常使用的循环的循环。)
private void receive() {
try {
while(running) {
int offset = 0;
byte[] header = new byte[4];
// receive header bytes from tcp stream
while (offset < header.Length) {
offset += clientSocket.Receive(header, offset, header.Length - offset, SocketFlags.None);
}
int bytesToRead = BitConverter.ToInt32(header, 0);
// receive body bytes from tcp stream
offset = 0;
byte[] data = new byte[bytesToRead];
while(offset < data.Length) {
offset += clientSocket.Receive(data, offset, data.Length - offset, SocketFlags.None);
}
// 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();
}
}但是,如果从System.Net.Socket类切换到System.Net.TcpClient类,则可以大大简化代码。首先,如果不需要TotalBytesRtpIn进行更新,就可以停止发送标头,因为BinaryFormatter已经将其长度作为有效负载的内部字段存储起来,因此不需要反序列化。然后,您所需要做的就是从NetworkStream获取TcpClient,并在数据包进入时进行处理。
private TcpClient _client; // Set this wherever you had your original Socket set up.
private void receive() {
try {
using(var stream = _client.GetStream()) {
BinaryFormatter bf = new BinaryFormatter();
while(running) {
#region This part is not needed if you are only going to deserialize the stream and not update TotalBytesRtpIn, make sure the server stops sending the header too!
int offset = 0;
byte[] header = new byte[4];
// receive header bytes from tcp stream
while (offset < header.Length) {
offset += stream.Read(header, offset, header.Length - offset);
}
int bytesToRead = BitConverter.ToInt32(header, 0);
#endregion
packet = (NetworkPacket)bf.Deserialize(stream);
// deliver network packet to listeners
if(packet!=null) {
this.onNetworkPacketReceived?.Invoke(packet);
}
// update network statistics
NetworkStatistics.getInstance().TotalBytesRtpIn += bytesToRead;
}
}
}
//These may need to get changed.
} 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();
}
}发布于 2017-06-13 22:09:44
正如Scott建议的那样,我用更安全的方法替换了读取消息头的不安全行:
private void receive() {
try {
while(running) {
if(clientSocket.Available>=4) {
// receive header bytes from tcp stream
byte[] header = new byte[4];
clientSocket.Receive(header, 4, SocketFlags.None);
int bytesToRead = BitConverter.ToInt32(header, 0);
// receive body bytes from tcp stream
int offset = 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();
}
}现在它运行得完美无缺:)非常感谢您的帮助!
https://stackoverflow.com/questions/44531259
复制相似问题