using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
namespace SilverlightSocketDemo.Server
{
[XmlInclude(typeof(MyMessage))]
public abstract class NetworkMessage
{
public static readonly int LENGTH_BYTES = 4;
//first 4 bytes of the buffer will contain the length of the serialized NetworkMessage
//this function treats input argument as immutable
public static NetworkMessage Deserialize(byte[] buffer)
{
int length = BitConverter.ToInt32(buffer, 0);
int startIndex = sizeof(int);
string strNetworkMessage = Encoding.UTF8.GetString(buffer, startIndex, length);
StringReader stringReader = new StringReader(strNetworkMessage);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(NetworkMessage));
return (NetworkMessage)xmlSerializer.Deserialize(stringReader);
}
//the first 4 bytes of the serialized byte array will contain the length of the buffer that
//contains the previously serialized NetworkMessage;
public static byte[] Serialize(NetworkMessage msg)
{
StringWriter stringWriter = new StringWriter();
XmlSerializer xmlSerializer = new XmlSerializer(typeof(NetworkMessage));
xmlSerializer.Serialize(stringWriter, msg);
byte[] messageBytes = Encoding.UTF8.GetBytes(stringWriter.ToString());
byte[] lengthBytes = BitConverter.GetBytes(messageBytes.Length);
byte[] finalBytes = new byte[lengthBytes.Length + messageBytes.Length];
//copy the length of the serialized object
Array.Copy(lengthBytes, 0, finalBytes, 0, lengthBytes.Length);
Array.Copy(messageBytes, 0, finalBytes, lengthBytes.Length, BitConverter.ToInt32(lengthBytes, 0));
return finalBytes;
}
}
public class MyMessage : NetworkMessage
{
public string User { get; set; }
public string Content { get; set; }
public override string ToString()
{
return User+":"+Content;
}
}
public class SocketBuffer
{
public const int BUFFERSIZE = 1024;
protected byte[] _buffer;
protected int _offset = 0;
public SocketBuffer()
{
_buffer = new byte[BUFFERSIZE];
}
public SocketBuffer(int size)
{
_buffer = new byte[size];
}
public byte[] Buffer
{
get { return _buffer; }
set { _buffer = value; }
}
//offset will allways indicate the length of the buffer that is filled
public int Offset
{
get { return _offset; }
set { _offset = value; }
}
public int Remaining
{
get { return _buffer.Length - _offset; }
}
}
public class ReceiveBuffer : SocketBuffer
{
//removes a serlialized message from the buffer, copies the partial message to the begining
//and adjusts the offset
public void AdjustBuffer()
{
int messageSize = BitConverter.ToInt32(_buffer, 0);
int lengthToCopy = _offset - NetworkMessage.LENGTH_BYTES - messageSize;
Array.Copy(_buffer, _offset, _buffer, 0, lengthToCopy);
_offset = lengthToCopy;
}
//this method checks if a complete message is received
public bool IsMessageReceived()
{
if (_offset < 4)
return false;
int sizeToRecieve = BitConverter.ToInt32(_buffer, 0);
//check if we have a complete NetworkMessage
if ((_offset - 4) < sizeToRecieve)
return false; //we have not received the complete message yet
//we received the complete message and may be more
return true;
}
}
}