Answer the question
In order to leave comments, you need to log in
OutOfMemoryException in BinaryFormatter on small volumes, why does it occur?
There is a client which accepts the data from the server. The SuperSocket library is used.
Well, that's not even the point here.
A filter has been created to receive data.
Data from the server comes into it, then I parse it in some way and then deserialize it.
Here is the whole problem. Deserialization sometimes throws an OutOfMemoryException, Function evaluation is disabled due to an out-of-memory exception, Array dimensions have exceeded the supported range.
From the server for the test, 100 serialized objects are simply sent, the weight of one object is 183 bytes.
The client can receive 3 objects and give an error, it can receive 6, maybe 20, in short, depending on the mood. Although the objects are always sent the same. Well, once I launched the program, it received 5 and gave an error, the second time already 3 and an error ... The riddle of krch.
The error is exactly when calling the Deserialize method.
What could be the reason?
public class RecieveFilterX : IReceiveFilter<DataPackageInfo>{
public DataPackageInfo Filter(BufferList data, out int rest){
if (data.Total > 4){
byte[] head = new byte[4];
Buffer.BlockCopy(data[0].Array, 0, head, 0, 4);
int sizeContent = BitConverter.ToInt32(head, 0);
if (data.Total >= sizeContent + 4){
int needCopiedBytes = sizeContent + 4;
using (MemoryStream msTemp = new MemoryStream()){
for (int i = 0; i < data.Count && needCopiedBytes > 0; i++){
int lenCopy = Math.Min(needCopiedBytes, data[i].Count);
msTemp.Write(data[i].Array, data[i].Offset, lenCopy);
needCopiedBytes -= lenCopy;
}
msTemp.Seek(4, SeekOrigin.Begin);
try{
BinaryFormatter formatter = new BinaryFormatter();
Message msg = (Message)formatter.Deserialize(msTemp);//Ошибка возникает тут
rest = data.Total - sizeContent - 4;
return new DataPackageInfo(){
Data = msg
};
}
catch (OutOfMemoryException ex){
//Вычисление функции отключено из-за исключения, вызванного нехваткой памяти
//Измерения массива превысили поддерживаемый диапазон
throw ex;
}
}
}
}
rest = 0;
return null;
}
public void Reset()
{
}
public IReceiveFilter<DataPackageInfo> NextReceiveFilter { get; set; }
public FilterState State { get; set; }
}
class DataRecieveFilter : IReceiveFilter<DataRequestInfo> {
private byte[] reserveBuff;
public DataRequestInfo Filter(byte[] readBuffer, int offset, int length, bool toBeCopied, out int rest) {
byte[] localBuffer = new byte[length];
if (reserveBuff != null && reserveBuff.Length > 0){
localBuffer = new byte[reserveBuff.Length + length];
Buffer.BlockCopy(reserveBuff, 0, localBuffer, 0, reserveBuff.Length);
Buffer.BlockCopy(readBuffer, offset, localBuffer, reserveBuff.Length, length);
reserveBuff = null;
}
else
Buffer.BlockCopy(readBuffer,offset,localBuffer,0,length);
if (localBuffer.Length > 4){
byte[] head = new byte[4];
Buffer.BlockCopy(localBuffer, 0, head, 0, 4);
int sizeContent = BitConverter.ToInt32(head, 0);
if (localBuffer.Length >= sizeContent + 4){
BinaryFormatter formatter = new BinaryFormatter();
byte[] dataMessage = new byte[sizeContent];
Buffer.BlockCopy(localBuffer, 4, dataMessage, 0, sizeContent);
using (MemoryStream msTemp = new MemoryStream(dataMessage)){
Message msg = (Message) formatter.Deserialize(msTemp);
rest = localBuffer.Length - sizeContent - 4;
return new DataRequestInfo()
{
Key = msg.key,
message = msg
};
}
}
}
rest = 0;
reserveBuff = localBuffer;
return null;
}
public void Reset()
{
reserveBuff = null;
}
public int LeftBufferSize { get; set; }
public IReceiveFilter<DataRequestInfo> NextReceiveFilter { get; set; }
public FilterState State { get; set; }
}
Answer the question
In order to leave comments, you need to log in
I wrote to you how to implement FixedHeader in the client.
internal class PackageInfo : PackageInfo<FrameType, Frame>
{
public PackageInfo(FrameType key, Frame body) : base(key, body)
{
}
}
internal class ReceiveFilter : FixedHeaderReceiveFilter<PackageInfo>
{
public ReceiveFilter(int headerSize) : base(headerSize)
{
}
public override PackageInfo ResolvePackage(IBufferStream bufferStream)
{
//реализация получения пакета из потока
}
protected override int GetBodyLengthFromHeader(IBufferStream bufferStream, int length)
{
var frameLength = bufferStream.ReadInt32(true);
return frameLength - HeaderSize;
}
}
var client = new EasyClient<PackageInfo>();
client.Initialize(new ReceiveFilter(4));
client.NoDelay = true;
client.ReceiveBufferSize = 10240;
client.NewPackageReceived += NewPackageReceived;
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question