-- 作者:bibiye -- 发布时间:2005-2-1 16:39:22
-- 完整的TCP通信包实现 using System; namespace Jh.Sockets { /// <summary> /// 线程状态信号定义 /// </summary> public enum JhThreadStatus { Stop, //停止 Running, //正在运行 Exit //已退出 } /// <summary> /// 线程状态参数 /// </summary> class Parm { public Parm(object obj):this(JhThreadStatus.Stop,obj) { } public Parm(JhThreadStatus nStatus,object obj) { Status = nStatus; ObjParm = obj; } JhThreadStatus status; object objParm; /// <summary> /// 上下文对象 /// </summary> public object ObjParm { get { return objParm; } set { objParm = value; } } /// <summary> /// 控制状态 /// </summary> public JhThreadStatus Status { get { return status; } set { status = value; } } }; /// <summary> /// 通讯数据处理接口 /// </summary> public interface IObserver { // // 数据处理入口 // void Deal(CommData cd); // // 数据处理重载方法.如果不希望后面的处理者继续处理数据,则返回true,否则返回false; // bool OnDeal(CommData cd); // // 附加的自身初始化操作 // bool Init(); // // 提前初始化接口 // bool BeforeInit(); // // 初始化后处理接口 // bool AfterInit(); // // 删除前处理接口 // bool BeforeExit(); // // 下一个观察者 // IObserver Next { get; set; } // // 上一个观察者 // IObserver Prev { get; set; } // // 添加观察者到后面,如果已经存在链表中则不做任何操作 // void Add(IObserver observer); // // 插入观察者到下一个观察者的前面 // void Insert(IObserver observer); //删除观察者 void Remove(IObserver observer); //是否存在链表中 bool IsExist(IObserver observer); } /// <summary> /// 通讯数据处理类的基类,只能派生 /// </summary> public abstract class Observer : IObserver { /// <summary> /// 数据处理入口. /// </summary> /// <param name="client">TcpClient类 实例</param> /// <param name="s">内存数据流</param> public void Deal(CommData cd) { cd.Data.Position = 0; if (OnDeal(cd) == false) return ; if (next != null) { next.Deal(cd); } return ; } /// <summary> /// 数据处理重载方法. /// </summary> /// <param name="client">TcpClient类 实例</param> /// <param name="s">内存数据流</param> /// <returns>处理结果,如果不希望后面的处理者继续处理数据,则返回false,否则返回true;</returns> public virtual bool OnDeal(CommData cd) { return true; } //附加的自身初始化操作 public virtual bool Init() { return true; } //提前初始化接口 public virtual bool BeforeInit() { return true; } //初始化后处理接口 public virtual bool AfterInit() { return true; } //删除前处理接口 public virtual bool BeforeExit() { return true; } //下一个观察者 IObserver next = null; public IObserver Next { get { return next; } set { next = value; } } //上一个观察者 IObserver prev = null; public IObserver Prev { get { return prev; } set { prev = value; } } //添加观察者 public void Add(IObserver observer) { if (this == observer) return;//已经存在 if (next == null) { next = observer;//达到最底端 next.Prev = this; } else next.Add(observer);//加到后面 } /// <summary> /// 插入观察者到下一个观察者的前面 /// </summary> /// <param name="observer"></param> public void Insert(IObserver observer) { //是否等于自己 if (this == observer) return; //先查找是否已经存在链表中 if (Next != null && Next.IsExist(observer)) Next.Remove(observer); // observer.Next = Next; if (Next != null) Next.Prev = observer; Next = observer; observer.Prev = this; } /// <summary> /// 删除观察者 /// </summary> /// <param name="observer"></param> public void Remove(IObserver observer) { if (observer == this) { if (Prev != null) Prev.Next = Next; if (Next != null) Next.Prev = Prev; } else { if (Next != null) Next.Remove(observer); } } /// <summary> /// 查找是否存在 /// </summary> /// <param name="observer"></param> /// <returns></returns> public bool IsExist(IObserver observer) { if (observer == this) return true; if (Next == null) return false; else return Next.IsExist(observer); } } /// <summary> /// 日志处理基类,本身从通讯数据处理类的基类派生。 /// </summary> class Log : Observer { public Log() { } public Log(string slogfile) { LogFile = slogfile; } ~Log() { } // 日志文件带路径名称 private string logFile; public string LogFile { get { return logFile; } set { logFile = value; } } } } using System; using System.Collections; using System.IO; using System.Threading; namespace Jh.Sockets { /// <summary> /// 数据集中管理类 /// </summary> public class CommDataMgr { static int index = 0; int id; /// <summary> /// 无参数构造方法 /// </summary> public CommDataMgr() { id = index ++; dnFlag = new Parm(this); Console.WriteLine("JH data distributor {0} constructed",id); } Thread t = null; public void Start() { if (dnFlag.Status != JhThreadStatus.Running) { dnFlag.Status = JhThreadStatus.Running; t = new Thread (new ThreadStart(DataNotiyfyThread)); t.Name = "JH data distributing " + id.ToString(); t.Start(); Console.WriteLine("JH data distributing thread of JH data distributor {0} started",id); } } public void Stop() { if ( dnFlag.Status == JhThreadStatus.Running ) { lock (this) { dnFlag.Status = JhThreadStatus.Stop; } } } /// <summary> /// 析构方法 /// </summary> ~CommDataMgr() { Stop(); Console.WriteLine("JH data distributor {0} unconstructed",id); } public void DataNotiyfyThread() { try { while (dnFlag.Status == JhThreadStatus.Running) { DealData(); Thread.Sleep(100); // Console.WriteLine("分发线程{0}工作中",id); } } catch(Exception e) { Console.WriteLine(e.Message); } finally { lock(this) { dnFlag.Status = JhThreadStatus.Exit; } Console.WriteLine("JH data distributing thread of JH data distributor {0} exited",id); } } Parm dnFlag = null; ArrayList aData = new ArrayList(); InnerObserver root = new InnerObserver(); /// <summary> /// 观察者根节点类 定义 /// </summary> internal class InnerObserver : Observer { } public void DealData() { if (DataCount > 0) { lock(this) { if (root.Next != null) { root.Next.Deal((CommData)aData[0]); } RemoveAt(0); } } } /// <summary> /// 未处理数据个数 /// </summary> public int DataCount { get { return aData.Count; } } /// <summary> /// 根据索引返回未处理数据 /// </summary> internal CommData this[int Index] { get { return (CommData)aData[Index]; } } /// <summary> /// 根据索引删除数据 /// </summary> /// <param name="Index">索引</param> public void RemoveAt(int Index) { if (Index >= 0 && Index < DataCount) { lock (this) { aData.RemoveAt(Index); } } } /// <summary> /// 接收到新的数据提交 /// </summary> /// <param name="client">客户端连接</param> /// <param name="s">数据流</param> public void AddData(JhClient client,MemoryStream s,int len) { CommData cd = new CommData(client,s,len,this); lock(this) { aData.Add(cd); } } /// <summary> /// 添加观察者 /// </summary> /// <param name="observer"></param> public void Add(IObserver observer) { lock (this) { root.Add(observer); } } /// <summary> /// 删除观察者 /// </summary> /// <param name="observer"></param> public void Remove(IObserver observer) { lock (this) { root.Remove(observer); } } /// <summary> /// 在最前面插入观察者 /// </summary> /// <param name="observer"></param> public void Insert(IObserver observer) { lock (this) { root.Insert(observer); } } // 取观察者个数 // int GetObserverCount() // { // return (int)m_aObservers.GetCount(); // } } } using System; using System.Threading; using System.Net.Sockets; using System.IO; using System.Collections; using System.Windows.Forms; using System.Net; namespace Jh.Sockets { /// <summary> /// 内部通信消息 /// </summary> enum JhCommMessages { MessageStart = 9909,//消息起始 DataTransfer, //数据传输 Disconnected, //连接将要断开 ConnectSignal, //连接检查信号 ConnectCheck, //启动连接信号 StopCheck, //停止连接信号 Unknown = 9999 //未知 } /// <summary> /// 通信数据 /// </summary> public class CommData { public CommData(JhClient client,MemoryStream stream,int len,CommDataMgr dm) { jhClient = client; Data = new MemoryStream(); stream.WriteTo(Data); dataLen = len; adm = dm; } JhClient jhClient; MemoryStream data; int dataLen; CommDataMgr adm; /// <summary> /// tcp连接 /// </summary> public JhClient Socket { get { return jhClient; } } /// <summary> /// 内存数据流 /// </summary> public MemoryStream Data { get { return data; } set { data = value; } } /// <summary> /// 数据长度 /// </summary> public int DataLen { get { return dataLen; } } }; public delegate void CommEventHandler(object sender,CommEventArgs e); public class CommEventArgs : EventArgs { public CommEventArgs(string msg):base() { Message = msg; } string message; public string Message { get { return message; } set { message = value; } } } /// <summary> /// Tcp通信客户类 /// </summary> public class JhClient { /// <summary> /// 连接成功事件 /// </summary> public event CommEventHandler OnConnected; /// <summary> /// 连接关闭事件 /// </summary> public event CommEventHandler OnClosed; /// <summary> /// 连接失败事件 /// </summary> public event CommEventHandler OnConnectFailed; /// <summary> /// 构造方法 /// </summary> /// <param name="dm">外部植入的数据管理类</param> /// <param name="ob">观察者</param> /// <param name="tcpClient">通信连接</param> public JhClient(CommDataMgr dm,IObserver ob,TcpClient tcpClient) { // // TOD 在此处添加构造函数逻辑 // status = new Parm(this); checkStatus = new Parm(this); autoConnectStatus = new Parm(this); if (dm == null) { adm = new CommDataMgr(); } else adm = dm; if (ob != null) adm.Add(ob); if (tcpClient == null) { client = new TcpClient(); } else client = tcpClient; ID = index ++; OnClosed += new CommEventHandler(OnConnectClosed); Console.WriteLine("JH tcp client {0} constructed",ID); } static int index = 0; /// <summary> /// 无参数构造函数 /// </summary> public JhClient(TcpClient tcpClient) : this(null,null,tcpClient) {} public JhClient(CommDataMgr dm,TcpClient tcpClient) : this(dm,null,tcpClient) {} public JhClient(IObserver ob,TcpClient tcpClient):this(null,ob,tcpClient) {} public JhClient() : this(null,null,null) {} public JhClient(CommDataMgr dm) : this(dm,null,null) {} public JhClient(IObserver ob):this(null,ob,null) {} /// <summary> /// 析构方法 /// </summary> ~JhClient() { AutoConnect = false; ConnectCheck = false; Close(); Console.WriteLine("JH tcp client {0} unconstructed",ID); } Parm status = null; /// <summary> /// 唯一标志符 /// </summary> int id = -1; public int ID { get { return id; } set { id = value; } } /// <summary> /// 连接状态 /// </summary> bool connected = false; public bool Connected { get { return connected; } set { connected = value; if (connected == true) { adm.Start(); if (status.Status != JhThreadStatus.Running) { status.Status = JhThreadStatus.Running; readThread = new Thread(new ThreadStart(this.DataReadThread)); readThread.Name = "Data reader of JH tcp client " + ID.ToString(); readThread.Start(); Console.WriteLine("Data reader of JH tcp client {0} started",ID); LastReceivedTime = DateTime.Now; if (ConnectCheck == true) { SendMessage(JhCommMessages.ConnectCheck,(Int32)CheckTimeout.Ticks); StartConnectCheckThread(); } } } else { status.Status = JhThreadStatus.Stop; if (OnClosed != null) OnClosed(this,new CommEventArgs("连接已经断开!")); } } } /// <summary> /// 尝试连接次数 /// </summary> int connectTimes = 0; /// <summary> /// 读取数据线程 /// </summary> Thread readThread = null; /// <summary> /// 自动断线重连标志 /// </summary> bool autoConnect = false; /// <summary> /// 自动断线重连标志 /// </summary> public bool AutoConnect { get { return autoConnect; } set { autoConnect = value; if (autoConnect != true) { lock(this) { autoConnectStatus.Status = JhThreadStatus.Stop; } } } } /// <summary> /// 自动连接间隔毫秒数 /// </summary> int autoConnectInterval = 3000; /// <summary> /// 自动连接间隔毫秒数 /// </summary> public int AutoConnectInterval { get { return autoConnectInterval; } set { autoConnectInterval = value; } } /// <summary> /// 连接检测的状态控制 /// </summary> Parm checkStatus = null; /// <summary> /// 自动连接的状态控制 /// </summary> Parm autoConnectStatus = null; /// <summary> /// 连接监测标志 /// </summary> bool connectCheck = false; /// <summary> /// 连接监测标志 /// </summary> public bool ConnectCheck { get { return connectCheck; } set { bool b = value; if (connectCheck != b) { if (connectCheck != true)//启动检测 { lock(this) { checkStatus.Status = JhThreadStatus.Stop; } if (Connected == true) { SendMessage(JhCommMessages.StopCheck); } } else { if (Connected == true) StartConnectCheckThread(); } } } } /// <summary> /// 启动连接检测线程 /// </summary> void StartConnectCheckThread() { if (checkStatus.Status != JhThreadStatus.Running) { checkStatus.Status = JhThreadStatus.Running; Thread t = new Thread(new ThreadStart(ConnectCheckThread)); t.Name = "JH tcp client connecting checker of JH tcp client " + this.ID.ToString(); t.Start(); Console.WriteLine(t.Name + " started."); } } /// <summary> /// 连接关闭事件响应 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public virtual void OnConnectClosed(object sender,CommEventArgs e) { if (AutoConnect == true)//是否自动重连 { StartAutoConnectThread(); } } /// <summary> /// 启动自动重连线程 /// </summary> void StartAutoConnectThread() { if (autoConnectStatus.Status != JhThreadStatus.Running) { connectTimes = 0; autoConnectStatus.Status = JhThreadStatus.Running; Thread t = new Thread(new ThreadStart(AutoConnectThread)); t.Name = "JH tcp client auto-connector of JH tcp client " + this.ID.ToString(); t.Start(); Console.WriteLine(t.Name + " started."); } } /// <summary> /// 最近一次通讯时间 /// </summary> DateTime lastReceivedTime = DateTime.Now; /// <summary> /// 最近一次通讯时间 /// </summary> public DateTime LastReceivedTime { get { return lastReceivedTime; } set { lastReceivedTime = value; } } /// <summary> /// 连接检测断开判断的最大允许毫秒数 /// </summary> TimeSpan checkTimeout = new TimeSpan(1800000000);//3 minutes /// <summary> /// 连接检测断开判断的最大允许毫秒数 /// </summary> public TimeSpan CheckTimeout { get { return checkTimeout; } set { TimeSpan ts = value; if (ts.Minutes > 2) checkTimeout = ts;//检查时间间隔不小于2分钟 } } /// <summary> /// 自动连接线程 /// </summary> void AutoConnectThread() { try { while (autoConnectStatus.Status == JhThreadStatus.Running && AutoConnect == true) { if (Connected != true) { DoConnect(); Thread.Sleep(AutoConnectInterval); } else { break; } } } catch (Exception e3) { MessageBox.Show(e3.Message); } finally { lock (this) { autoConnectStatus.Status = JhThreadStatus.Exit; } } } /// <summary> /// 连接检测线程 /// </summary> void ConnectCheckThread() { try { while (checkStatus.Status == JhThreadStatus.Running) { if (Connected == true) { TimeSpan ts = DateTime.Now - lastReceivedTime; TimeSpan ts2 = CheckTimeout + CheckTimeout; if (ts > ts2 )//超过两倍间隔时间,认为已经断开 { Close(); break; } else { SendMessage(JhCommMessages.ConnectSignal,(Int32)CheckTimeout.Ticks); } } else { LastReceivedTime = DateTime.Now; break; } Thread.Sleep(checkTimeout); } } catch (Exception e3) { MessageBox.Show(e3.Message); } finally { lock(this) { checkStatus.Status = JhThreadStatus.Exit; } Console.WriteLine("JH tcp client connecting checker of JH tcp client " + this.ID.ToString() + " exited.") ; } } /// <summary> /// 读取数据的线程 /// </summary> void DataReadThread() { try { while (status.Status == JhThreadStatus.Running) { if (Connected == true) { NetworkStream ns = Client.GetStream(); int readCount,totalRead = 0; while (ns.DataAvailable == true)//读取数据,转存到s中,因为NetworkStream的数据只能向前读取一次 { readCount = ns.Read(buffer, 0, bufferSize); if (readCount > 0) { buf.Write(buffer, 0, readCount); totalRead += readCount; } else { break; } } ; if (totalRead > 0)//有数据 { DealData();//处理 } } Thread.Sleep(50); } } catch(IOException e3) { MessageBox.Show(e3.Message); } catch (ObjectDisposedException e2) { MessageBox.Show(e2.Message); } catch (InvalidOperationException e1) { MessageBox.Show(e1.Message); } catch (Exception e3) { MessageBox.Show(e3.Message); } finally { lock(this) { status.Status = JhThreadStatus.Exit; } Console.WriteLine("Data reader thread of JH tcp client {0} exited.",ID); } } /// <summary> /// 服务器ip /// </summary> string ipString; /// <summary> /// 服务器端口 /// </summary> int tcpPort; /// <summary> /// 根据当前设置的ip和 port参数进行连接 /// </summary> void DoConnect() { try { if (Connected == false) { if (Client == null) { Client = new TcpClient(); } ++ connectTimes ; Client.Connect(ipString,tcpPort); Connected = true; autoConnectStatus.Status = JhThreadStatus.Stop; if (OnConnected != null) OnConnected(this,new CommEventArgs("已经与服务器建立连接!")); } } catch(Exception le) { if (OnConnectFailed != null) OnConnectFailed(this,new CommEventArgs("第" + connectTimes.ToString() + "次与服务器建立连接失败!" + le.Message)); } } /// <summary> /// 连接服务器 /// </summary> /// <param name="ip"></param> /// <param name="port"></param> public void Connect(string ip,int port) { ipString = ip; tcpPort = port; if (this.AutoConnect == true) { StartAutoConnectThread(); } else { DoConnect(); } } /// <summary> /// 发送数据 /// </summary> /// <param name="data"></param> /// <returns></returns> public void Send(string data) { Send( data, System.Text.Encoding.Default); } /// <summary> /// 发送数据 /// </summary> /// <param name="data"></param> /// <returns></returns> public void Send(string data, System.Text.Encoding encodingway) { byte[] dt = encodingway.GetBytes(data); Send(dt); } /// <summary> /// 发送数据 /// </summary> /// <param name="data"></param> /// <returns></returns> public void Send(byte[] data) { if (Connected == true) { CommHead ch = new CommHead(); ch.WParam = (short)JhCommMessages.DataTransfer; ch.Add(data); client.GetStream().Write(ch.ToBytes(),0,ch.Length); } else { MessageBox.Show("尚未建立连接或者连接已经断开!"); } } /// <summary> /// 关闭连接 /// </summary> public void Close() { if (Connected == true) { SendMessage(JhCommMessages.Disconnected); Connected = false; adm.Stop(); Client.Close(); Client = null; } } /// <summary> /// 程序退出时调用,或者设置AutoConnect = false /// </summary> public void Exit() { AutoConnect = false; ConnectCheck = false; Close(); } /// <summary> /// TCP客户对象 /// </summary> TcpClient client = null; /// <summary> /// TCP客户对象 /// </summary> public TcpClient Client { get { return client; } set { client = value; } } /// <summary> /// 缓存未处理的数据 /// </summary> MemoryStream buf = new MemoryStream(); /// <summary> /// 读取接收到的数据的缓冲区的大小 /// </summary> const int bufferSize = 1024; /// <summary> /// 读取接收到的数据的缓冲区 /// </summary> byte[] buffer = new byte[bufferSize]; /// <summary> /// 数据分发管理者 /// </summary> CommDataMgr adm ; /// <summary> /// 数据分发管理者 /// </summary> public CommDataMgr DataMgr { set { adm = value; } } /// <summary> /// 接收到的数据的处理 /// </summary> private void DealData() { // if (buf.Length > 0) //有数据需要处理 { CommHead chio = new CommHead(buf,(int)buf.Position); if (chio.IsValid()) { LastReceivedTime = DateTime.Now; if (chio.DataLen > 0)//有效数据 { adm.AddData(this,chio.GetData(),chio.DataLen);//可处理数据 } else//纯内部消息 { switch ((JhCommMessages)chio.WParam) { case JhCommMessages.Disconnected: //对方将要断开连接消息 Close(); break; case JhCommMessages.ConnectCheck: if (CheckTimeout.Ticks != chio.DWParam) { CheckTimeout = new TimeSpan(chio.DWParam); } ConnectCheck = true; break; case JhCommMessages.StopCheck: ConnectCheck = false; break; case JhCommMessages.ConnectSignal: if (CheckTimeout.Ticks != chio.DWParam) { CheckTimeout = new TimeSpan(chio.DWParam); } break; default: break; } } buf.Position = 0; chio.GetLeftData(ref buf);//剩下未处理完数据 } } } /// <summary> /// 不带参数的消息 /// </summary> /// <param name="message"></param> private void SendMessage(JhCommMessages message) { SendMessage(message,0); } /// <summary> /// 带参数的消息 /// </summary> /// <param name="message"></param> private void SendMessage(JhCommMessages message,Int32 parm) { CommHead ch = new CommHead(); ch.WParam = (short)message; ch.DWParam = parm; Client.GetStream().Write(ch.ToBytes(),0,16); } } /// <summary> /// Tcp通信服务器类 /// </summary> public class JhTcpServer { public JhTcpServer(int port) { IPAddress ipAddress = IPAddress.Parse("127.0.0.1");//Dns.Resolve("localhost").AddressList[0]; server = new TcpListener(ipAddress,port); adm = new CommDataMgr(); status = new Parm(this); } ~JhTcpServer() { Stop(); } /// <summary> /// Tcp监听对象 /// </summary> TcpListener server = null; /// <summary> /// 客户端序号 /// </summary> int clientindex = 0; /// <summary> /// 开始监听 /// </summary> public void Start() { clients.Clear(); clientindex = 99999999; adm.Start(); server.Start(); status.Status = JhThreadStatus.Running; listenThread = new Thread(new ThreadStart(this.ListenThread)); listenThread.Name = "JH tcp listenor"; listenThread.Start(); Console.WriteLine("JH tcp listenor started."); } /// <summary> /// 监听线程 /// </summary> Thread listenThread = null; /// <summary> /// 停止接受连接 /// </summary> public void Stop() { int i; for (i = 0; i < this.clients.Count; ++i) { StopClient(i); } adm.Stop(); if (status.Status == JhThreadStatus.Running) { lock(this) { status.Status = JhThreadStatus.Stop; } while (status.Status != JhThreadStatus.Exit) { Thread.Sleep(100); } } server.Stop(); } /// <summary> /// 断开指定索引的客户 /// </summary> /// <param name="index">客户端索引</param> public void StopClient(int index) { GetClient(index).Exit(); } /// <summary> /// 发送数据 /// </summary> /// <param name="data"></param> /// <returns></returns> public void Send(JhClient client,string data) { if (client != null) { byte[] dt = System.Text.Encoding.Default.GetBytes(data); client.Send(dt); } } /// <summary> /// 用最后一个客户端发送数据 /// </summary> /// <param name="data"></param> public void Send(string data) { Send(GetClient(clients.Count - 1),data); } /// <summary> /// 数据分发管理者 /// </summary> CommDataMgr adm ; Parm status = null; /// <summary> /// 客户连接线程 /// </summary> void ListenThread() { try { while (status.Status == JhThreadStatus.Running) { if (server.Pending() == true) { TcpClient client = server.AcceptTcpClient();//侦听到连接后创建客户端 JhClient jhClient = new JhClient(adm,client); jhClient.ID = clientindex--; SetClient(jhClient); jhClient.Connected = true; } Thread.Sleep(100); } } catch (ObjectDisposedException e2) { MessageBox.Show(e2.Message); } catch (InvalidOperationException e1) { MessageBox.Show(e1.Message); } catch (Exception e3) { MessageBox.Show(e3.Message); } finally { lock(this) { status.Status = JhThreadStatus.Exit; } Console.WriteLine("JH tcp listenor exited"); } } /// <summary> /// 添加观察者 /// </summary> /// <param name="ob"></param> public void AddOb(IObserver ob) { adm.Add(ob); } Hashtable clients = new Hashtable(); /// <summary> /// 根据内部id获取客户端 /// </summary> /// <param name="id"></param> /// <returns></returns> public JhClient GetClient(int id) { return (JhClient)clients[id]; } /// <summary> /// 设置客户端对象 /// </summary> /// <param name="client"></param> public void SetClient(JhClient client) { int i; for (i = 0 ; i < clients.Count; ++i) { if (((JhClient)clients[i]).ID == client.ID) { break; } } clients[i] = client; } } /// <summary> /// 通信头处理类 /// </summary> class CommHead { Int16 wHeadSize;// 头结构长度 Int16 wFlag;//合法数据包特征字 Int16 wVer;// 用版本号表示标识符 Int16 wParm;// 参数一 Int32 dwParm;// 参数二 Int32 dwDataLen;// 后续数据长度 /// <summary> /// 新建头构造方法 /// </summary> public CommHead() : this(System.Text.Encoding.Default) { Init(); } /// <summary> /// 新建头构造方法 /// </summary> public CommHead(System.Text.Encoding enCoding) { encoding = enCoding; Init(); } System.Text.Encoding encoding; /// <summary> /// 解析数据构造方法 /// </summary> /// <param name="s">数据流</param> public CommHead(MemoryStream s,int len) : this(s,len,System.Text.Encoding.Default) { } /// <summary> /// 解析数据构造方法 /// </summary> /// <param name="s">数据流</param> /// <param name="encoding">字符编码方案</param> public CommHead(MemoryStream s,int len,System.Text.Encoding encoding) { Init(); if (s != null) { s.Position = 0; BinaryReader r = new BinaryReader(s,encoding); wHeadSize = r.ReadInt16(); if (len >= wHeadSize) { wFlag = r.ReadInt16(); if (IsValid()) { wVer = r.ReadInt16(); wParm = r.ReadInt16(); dwParm = r.ReadInt32(); dwDataLen = r.ReadInt32(); if (dwDataLen > 0) { byte[] dt = r.ReadBytes(dwDataLen); if (dt != null) recvData = new MemoryStream(dt); else { recvData = null; dwDataLen = 0; } } if (len > wHeadSize + dwDataLen) { byte[] dt = r.ReadBytes(len - wHeadSize - dwDataLen); if (dt != null) moreData = new MemoryStream(dt); else moreData = null; } } } } } MemoryStream recvData; MemoryStream moreData; void Init() {wFlag = 0x4a48; wVer = 1; wHeadSize = 16; } // 当前头数据是否有效 public bool IsValid() {return wFlag == 0x4a48 && wHeadSize == 16; } // 返回双字节参数 public Int32 DWParam { get { return dwParm; } set { dwParm = value; } } // 返回单字节参数 public Int16 WParam { get { return wParm; } set { wParm = value; } } // 返回头结构大小 public Int16 HeadSize { get { return wHeadSize; } } // 返回版本标识符 public virtual Int16 Ver { get { return wVer; } } // 返回后续数据长度 public virtual Int32 DataLen { get { return dwDataLen; } set { dwDataLen = value; } } /// <summary> /// 返回未处理数据 /// </summary> /// <returns></returns> public void GetLeftData(ref MemoryStream s) { if (moreData != null) { moreData.WriteTo(s); moreData.Close(); } } /// <summary> /// 返回完整数据 /// </summary> /// <returns></returns> public MemoryStream GetData() { return recvData; } /// <summary> /// 添加数据 /// </summary> /// <param name="pszData"></param> public void Add(byte[] pszData) { data.Write(pszData,0,pszData.Length); dwDataLen += pszData.Length; } MemoryStream data = new MemoryStream(); /// <summary> /// 需要发送的数据转为字节数组 /// </summary> /// <returns></returns> public byte[] ToBytes() { MemoryStream s = new MemoryStream(); BinaryWriter w = new BinaryWriter(s,encoding); w.Write(wHeadSize); w.Write(wFlag); w.Write(wVer); w.Write(wParm); w.Write(dwParm); w.Write(dwDataLen); // w.Close(); data.WriteTo(s); return s.ToArray(); } /// <summary> /// 需要发送的数据的长度 /// </summary> public int Length { get { return (int)data.Length + wHeadSize; } } } } namespace Jh.Sockets { /// <summary> /// 字符串特性常量存放类 /// </summary> public class JhStringConst { public const int SHORT_STRING_LEN = 16; public const int NORMAL_STRING_LEN = 32; public const int MIDD_STRING_LEN = 64; public const int LONG_STRING_LEN = 128; public const int LONGER_STRING_LEN = 256; public const int EXLONG_STRING_LEN = 1024; } } |