Десериализация

 
0
 
.NET
ava
WERITAS | 20.08.2007, 10:37
Доброго времени суток! Почему-то приложение вылетает при попытке десериализовать объект.

Сообщение об ощибке:
Цитата


System.Runtime.Serialization.SerializationException: Binary stream '0' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization



Sockets.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace Server
{
class AsyncServer
{
public byte[] inBuff = new byte[1024];
public byte[] outBuff = new byte[1024];

public ManualResetEvent socketEvent = new ManualResetEvent(false);

public void AcceptCallback(IAsyncResult ar)
{
Console.WriteLine("AcceptCallback Thread ID:" + AppDomain.GetCurrentThreadId());
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);

handler.BeginReceive(outBuff, 0, outBuff.Length, 0, new AsyncCallback(ReceiveCallback), handler);
}

public void ReceiveCallback(IAsyncResult ar)
{
Console.WriteLine("ReceiveCallback Thread ID:" + AppDomain.GetCurrentThreadId());
string content = String.Empty;
Socket handler = (Socket)ar.AsyncState;
int byteRead = handler.EndReceive(ar);

if (byteRead > 0)
{
content += Encoding.ASCII.GetString(outBuff, 0, byteRead);

if (content.IndexOf(".") > -1)
{
Console.WriteLine("Read {0} bytes from Client. \nData: {1}", content.Length, content);
handler.BeginSend(inBuff, 0, inBuff.Length, 0, new AsyncCallback(SendCallback), handler);
}
else
{ }
}
}

public void SendCallback(IAsyncResult ar)
{
Console.WriteLine("SendCallback Thread ID:" + AppDomain.GetCurrentThreadId());

Socket handler = (Socket)ar.AsyncState;
int byteSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to Client.", byteSent);

handler.Shutdown(SocketShutdown.Both);
handler.Close();

socketEvent.Set();
}
}

class AsyncClient
{
public byte[] outBuff = new byte[1024];

public ManualResetEvent ConnectDone = new ManualResetEvent(false);
public ManualResetEvent SendDone = new ManualResetEvent(false);
public ManualResetEvent ReceiveDone = new ManualResetEvent(false);

public void ConnectCallback(IAsyncResult ar)
{
Thread thr = Thread.CurrentThread;
Console.WriteLine("ConnectCallback Thread State:" + thr.ThreadState);

Socket sClient = (Socket)ar.AsyncState;
sClient.EndConnect(ar);
Console.WriteLine("Socket connected to {0}", sClient.RemoteEndPoint.ToString());

ConnectDone.Set();
}

public void SendCallback(IAsyncResult ar)
{
Thread thr = Thread.CurrentThread;
Console.WriteLine("SendCallback Thread State:" + thr.ThreadState);

Socket sClient = (Socket)ar.AsyncState;
int byteSent = sClient.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server", byteSent);

SendDone.Set();
}

public void ReceiveCallback(IAsyncResult ar)
{
Thread thr = Thread.CurrentThread;
Console.WriteLine("ReceiveCallback Thread State:" + thr.ThreadState);

Socket sClient = (Socket)ar.AsyncState;
int byteRead = sClient.EndReceive(ar);

if (byteRead > 0)
{
sClient.BeginReceive(outBuff, 0, outBuff.Length, 0, new AsyncCallback(ReceiveCallback), sClient);
}
else
{
ReceiveDone.Set();
}
}
}
}


Questions.cs


using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.IO;

namespace Server
{
[Serializable]
public class SCollection
{
string varname;
int x1;
int x2;
int y1;
int y2;
string imagp;
Image imaga;

public void SetVarname(string st) { this.varname = st; }
public string GetVarname() { return this.varname; }

public void SetX1(int x_1) { this.x1 = x_1; }
public int GetX1() { return this.x1; }

public void SetX2(int x_2) { this.x2 = x_2; }
public int GetX2() { return this.x2; }

public void SetY1(int y_1) { this.y1 = y_1; }
public int GetY1() { return this.y1; }

public void SetY2(int y_2) { this.y2 = y_2; }
public int GetY2() { return this.y2; }

public void SetImagp(string ip) { this.imagp = ip; }
public string GetImagp() { return this.imagp; }

public void SetImaga(Image ia) { this.imaga = ia; }
public Image GetImaga() { return this.imaga; }

public SCollection()
{
varname = "";
x1 = 0;
x2 = 0;
y1 = 0;
y2 = 0;
imagp = "";
imaga = null;
}

public SCollection(string st, int x_1, int x_2, int y_1, int y_2, string ip, byte[] mass)
{
varname = st;
x1 = x_1;
x2 = x_2;
y1 = y_1;
y2 = y_2;
imagp = ip;
Stream stream = new MemoryStream(mass);
imaga = Image.FromStream(stream);
}

public SCollection(SCollection obj)
{
varname = obj.varname;
x1 = obj.x1;
x2 = obj.x2;
y1 = obj.y1;
y2 = obj.y2;
imagp = obj.imagp;
imaga = obj.imaga;
}
}

[Serializable]
public abstract class СQuestion
{
protected string Task;
protected string ImPath;
protected Image ImTask;
protected int Complic;
protected string Topic;
protected int TimeMin;
protected int TimeSec;
protected int Quantity;

public void SetTask(string ta) { this.Task = ta; }
public string GetAge() { return this.Task; }

public void SetImPath(string ip) { this.ImPath = ip; }
public string GetImPath() { return this.ImPath; }

public void SetImTask(Image it) { this.ImTask = it; }
public Image GetImTask() { return this.ImTask; }

public void SetComplic(int co) { this.Complic = co; }
public int GetComplic() { return this.Complic; }

public void SetTopic(string to) { this.Topic = to; }
public string GetTopic() { return this.Topic; }

public void SetTimeMin(int tm) { this.TimeMin = tm; }
public int GetTimeMin() { return this.TimeMin; }

public void SetTimeSec(int ts) { this.TimeSec = ts; }
public int GetTimeSec() { return this.TimeSec; }

public void SetQuantity(int qu) { this.Quantity = qu; }
public int GetQuantity() { return this.Quantity; }

public СQuestion()
{
Task = "";
ImPath = "";
ImTask = null;
Complic = 0;
Topic = "";
TimeMin = 0;
TimeSec = 0;
Quantity = 0;
}

public СQuestion(string ta, string ip, byte[] mass, int co, string to, int tm, int ts, int qu)
{
Task = ta;
ImPath = ip;
Stream stream = new MemoryStream(mass);
ImTask = Image.FromStream(stream);
Complic = co;
Topic = to;
TimeMin = tm;
TimeSec = ts;
Quantity = qu;
}
}

[Serializable]
public class CQuestionChoose : СQuestion
{
protected SCollection VarAnswer1;
protected SCollection VarAnswer2;
protected SCollection CorAnswer1;
protected SCollection CorAnswer2;

public void SetVarAnswer1(SCollection va1) { this.VarAnswer1 = va1; }
public SCollection GetVarAnswer1() { return this.VarAnswer1; }

public void SetVarAnswer2(SCollection va2) { this.VarAnswer2 = va2; }
public SCollection GetVarAnswer2() { return this.VarAnswer2; }

public void SetCorAnswer1(SCollection co1) { this.CorAnswer1 = co1; }
public SCollection GetCorAnswer1() { return this.CorAnswer1; }

public void SetCorAnswer2(SCollection co2) { this.CorAnswer2 = co2; }
public SCollection GetCorAnswer2() { return this.CorAnswer2; }

public CQuestionChoose()
{
VarAnswer1 = new SCollection("", 0, 0, 0, 0, "", null);
VarAnswer2 = new SCollection("", 0, 0, 0, 0, "", null);
CorAnswer1 = new SCollection("", 0, 0, 0, 0, "", null);
CorAnswer2 = new SCollection("", 0, 0, 0, 0, "", null);
}

public CQuestionChoose(string ta, string ip, byte[] mass, int co, string to, int tm, int ts, int qu, SCollection va1, SCollection va2, SCollection co1, SCollection co2)
: base(ta, ip, mass, co, to, tm, ts, qu)
{
VarAnswer1 = new SCollection(va1);
VarAnswer2 = new SCollection(va2);
CorAnswer1 = new SCollection(co1);
CorAnswer2 = new SCollection(co2);
}

}
}


Programm.cs


using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Drawing;
using System.Data;
using System.Data.SqlClient;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace Server
{
class Programm
{
static void Main(string[] args)
{
string c;
Console.WriteLine("1 - Server, 2- Client");
c = Console.ReadLine();

if(Int32.Parse(c) == 1)
{
Console.Title = "Server";

.........................................

/* Создание объектов класса SCollection */
Console.WriteLine("Creating SCollection object's massive...");
SCollection[] vars = new SCollection[4];
for(int i = 0; i < 4; i++)
{
vars[i] = new SCollection(..........................);
}

/* Создание объекта класса CQuestionChoose */
Console.WriteLine("Creating CQuestionChoose object...");
CQuestionChoose obj = new CQuestionChoose(............................);

/* Сериализация в двоичный формат через поток */
Console.WriteLine("Object is serializing...");
Stream inStm = new MemoryStream();
BinaryFormatter inFormatter = new BinaryFormatter();
inFormatter.Serialize(inStm, obj);

/* Чтение из потока в массив байтов(буффер)*/
int Len = (int)inStm.Length;
byte[] inBuff = new byte[Len];
//inStm.Position = 0;
inStm.Seek(0, SeekOrigin.Begin);
inStm.Read(inBuff, 0, Len);
inStm.Close();

/* Установка соединения */
string addr = "127.0.0.1";
string port = "20000";

IPHostEntry ipHost = Dns.Resolve(addr);
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint localEnd = new IPEndPoint(ipAddr, Int32.Parse(port));

AsyncServer AsyServ = new AsyncServer();
AsyServ.inBuff.CopyTo(inBuff, 0);

Socket sListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

sListener.Bind(localEnd);
sListener.Listen(1);
Console.WriteLine("Waiting for a connection...");

AsyncCallback aCallback = new AsyncCallback(AsyServ.AcceptCallback);
sListener.BeginAccept(aCallback, sListener);
AsyServ.socketEvent.WaitOne();
}
else
{
AsyncClient AsyClnt = new AsyncClient();

Thread thr = Thread.CurrentThread;
Console.WriteLine("Main Thread State:" + thr.ThreadState);

IPHostEntry ipHost = Dns.Resolve("127.0.0.1");
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint endPoint = new IPEndPoint(ipAddr, 20000);

try
{
Socket sClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

/* Соединение */
sClient.BeginConnect(endPoint, new AsyncCallback(AsyClnt.ConnectCallback), sClient);
AsyClnt.ConnectDone.WaitOne();

/* Отправление данных */
string data = "Give me an object";
byte[] byteData = Encoding.ASCII.GetBytes(data + ".");
sClient.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(AsyClnt.SendCallback), sClient);
AsyClnt.SendDone.WaitOne();

/* Получение данных */
byte[] outBuff = new byte[1024];
sClient.BeginReceive(outBuff, 0, outBuff.Length, 0, new AsyncCallback(AsyClnt.ReceiveCallback), sClient);
AsyClnt.ReceiveDone.WaitOne();
Console.WriteLine("Receive {0} bytes from server", outBuff.Length);

/* Десериализация */
Console.WriteLine("Object is deserializing...");
Stream outStm = new MemoryStream(outBuff);
BinaryFormatter outFormatter = new BinaryFormatter();
outStm.Seek(0, SeekOrigin.Begin);
CQuestionChoose rec = (CQuestionChoose)outFormatter.Deserialize(outStm);
outStm.Close();

sClient.Shutdown(SocketShutdown.Both);
sClient.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
/* Завершение приложения */
Console.WriteLine("Press any key to continue...");
Console.ReadLine();

}// Program
}
}



Удалось установить, что сервер неверно отправляет данные :( Но где ошибка?
Comments (1)
ava
tol05 | 21.08.2007, 12:03 #
WERITAS, было бы легче, если бы ты вместо

vars[i] = new SCollection(..........................);
...
CQuestionChoose(............................);

приводил бы полный код... Дебагать легче.

ИМХО, в AsyncClient.ReceiveCallback есть баг. По твоему коду получается, что если ты хоть что-то принял, то начинаешь дополнительно асинхронно принимать, но уже не в буфер

byte[] outBuff = new byte[1024];

который ты в Main создал, а во внутренний буфер AsyncClient.outBuff.
Т.е. допустим ты получил 1024 байта во внешний outBuff, а остальные хочешь получать в AsyncClient.outBuff, начиная с 0 позиции буфера? Как потом данные из массивов склеивать?
+ Если и во второй раз ты получил данные, то открываешь третий поток для чтения, потом четвертый ....
С массивами байт каша...

И еще в серверной части ошибка:

//AsyServ.inBuff - пустой, ты его копируешь в inBuff (содержащий данные), т.е. попросту затираешь свои же операции "Чтение из потока в массив байтов(буффер)" пустым массивом
//AsyServ.inBuff.CopyTo(inBuff, 0);

я написал бы

inBuff.CopyTo(AsyServ.inBuff, 0);
Please register or login to write.
Firm of day
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Contributors
  WERITAS   tol05
advanced
Submit