您的位置:首页 > 理论基础 > 计算机网络

Tcp 数据对象传输接口对象设计

2015-08-17 15:27 585 查看
输入是一个对象inputObj,接口对象.Send(inputObj),对端接收之后解包成outputObj(与inputObj应相同),触发onPackageReceive事件

事件

public event DataServiceHandler onPackageReceived;//收包事件:

   public event DataServiceHandler onPackageSent;//发包事件:
public event DataServiceHandler onPeerDisconnected;// 失连事件:
public event DataServiceHandler onSendingException;//发包异常事件;
public event DataServiceHandler onReceivingException;//收包异常时间;
public event DataServiceHandler onNotify;//对象通知事件(通知一些状态信息什么的)

成员

   SetClient()//关联Tcp连接到数据对象传输接口,复位数据对象状态,开始接收线程,允许发

   Reset()//复位数据对象状态,开始接收线程,允许发

   Stop()//停止接收线程,禁止发

Send()//发送数据对象

public class draftClass
{
#region Structure
#endregion

#region Fields
object locker;
TcpClient clientObj;
Messager messager=new Messager();
Thread recvThread;
#endregion

#region Events
public delegate void DataServiceHandler(string msg,object sender);
public event DataServiceHandler onPackageReceived;
public event DataServiceHandler onPackageSent;
public event DataServiceHandler onPeerDisconnected;
public event DataServiceHandler onSendingException;
public event DataServiceHandler onReceivingException;
public event DataServiceHandler onNotify;
#endregion

#region Functions
public void SetClient(TcpClient tc)
{
Stop();
clientObj = tc;
StartReceiving();
}
public void ReStart()
{
SetClient(this.clientObj);
}
public void Stop() { lock (recvThread) { recvThread.Abort(); } }

/// <summary>
/// 打包msg和数据对象,并发送
/// </summary>
/// <param name="msg"></param>
/// <param name="o"></param>
public void Send(string msg, object o)
{
byte[] m = new byte[100];
Encoding.UTF8.GetBytes(msg).CopyTo(m, 0);
byte[] data = ObjectToBytes(o);
byte[] d = new byte[m.Length + data.Length];
m.CopyTo(d, 0);
data.CopyTo(d, m.Length);

Send(this.clientObj.GetStream(), d);
}
public void StartReceiving()
{
Thread t = new Thread(new ThreadStart(Receiving));
t.Name = "[DataService] Receiving Thread";
t.Start();
}

private void Send(NetworkStream ns, byte[] d)
{
lock (this)
{
NetworkStream netStream = ns;
byte[] data = new byte[d.Length + 4];
System.BitConverter.GetBytes(d.Length).CopyTo(data, 0);
d.CopyTo(data, 4);

netStream.Write(data, 0, data.Length);
}
}
private void Receiving()
{
{
Console.WriteLine("In Thread({0}),WaitingData", Thread.CurrentThread.ManagedThreadId);
NetworkStream ns = clientObj.GetStream();
while (IsOnline())
{
while (ns.DataAvailable)
{
#if DEBUG
DateTime start = DateTime.Now;
#endif
//收到的数据为2进制的原始数据,数据交给分发器处理函数
byte[] data = ReceiveByteArray(ns);
Distributor(data);
#if DEBUG
TimeSpan ts = DateTime.Now - start;
double r = data.Length * 8 / (ts.TotalSeconds * 1024 * 1024);
Console.WriteLine("ReceiveByteArray Length={0}\tDuring={1:f0}ms\tRate= {2:f3} Mbps", data.Length, ts.TotalMilliseconds, r);
#endif
}
//Thread.Sleep(3);
}
Console.WriteLine("In Thread({0}),clientObj Disconnect!", Thread.CurrentThread.ManagedThreadId);

if (onPeerDisconnected != null)
onPeerDisconnected("Peer Disconnected",null);
Thread.CurrentThread.Abort();
}
}
//报文结构是自定义的2进制数据
//Part1:定长100字节,存放消息
//Part2:序列化了的数据对象
private void Distributor(byte[] data)
{
//解包
string msg = GetMsg(data);
object obj = GetObj(data);

//msg过Messager.Paser()
if (messager.TryParser(msg, obj))
return;

//如果Messager处理失败,触发onPackageReceived事件
if (onPackageReceived != null)
onPackageReceived("",data);
}
#region api
private string GetMsg(byte[] data) { return ""; }
private object GetObj(byte[] data) {return new object(); }
private byte[] ReceiveByteArray(NetworkStream stream)
{
try
{
int bufferlen = GetSize(stream);
byte[] resultbyte = new byte[bufferlen];

int offset = 0, bytesread = 0;
while (offset < bufferlen)
{
bytesread = stream.Read(resultbyte, offset, bufferlen - offset);
if (bytesread == 0)
{
Console.WriteLine("?????A");
throw new Exception("网络异常断开,数据读取不完整。");
}
else
offset += bytesread;
}
return resultbyte;
}
catch (Exception)
{
Console.WriteLine("?????B");
throw;
}
}
private int GetSize(NetworkStream stream)
{
try
{
int bufferlen = 4;
byte[] resultbyte = new byte[bufferlen];

int offset = 0, bytesread = 0;
while (offset < bufferlen)
{
bytesread = stream.Read(resultbyte, offset, bufferlen - offset);
if (bytesread == 0)
throw new Exception("网络异常断开,数据读取不完整。");
else
offset += bytesread;
}
return System.BitConverter.ToInt32(resultbyte, 0);
}
catch (Exception)
{
throw;
}
}
private bool IsOnline()
{
TcpClient c = this.clientObj;
return !((c.Client.Poll(1000, SelectMode.SelectRead) && (c.Client.Available == 0)) || !c.Client.Connected);
}
/// <summary>
/// 将一个object对象序列化,返回一个byte[]
/// </summary>
/// <param name="obj">能序列化的对象</param>
/// <returns></returns>
///
private byte[] ObjectToBytes(object obj)
{
using (MemoryStream ms = new MemoryStream())
{
IFormatter formatter = new BinaryFormatter(); formatter.Serialize(ms, obj); return ms.GetBuffer();
}
}
/// <summary>
/// 将一个序列化后的byte[]数组还原
/// </summary>
/// <param name="Bytes"></param>
/// <returns></returns>
private object BytesToObject(byte[] Bytes)
{
using (MemoryStream ms = new MemoryStream(Bytes))
{
IFormatter formatter = new BinaryFormatter(); return formatter.Deserialize(ms);
}
}
#endregion
#endregion
}


DataService.cs
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: