-- 作者:bibiye -- 發(fā)布時(shí)間:2005-2-1 16:39:22
-- 完整的TCP通信包實(shí)現(xiàn)
using System;
namespace Jh.Sockets { /// <summary> /// 線程狀態(tài)信號(hào)定義 /// </summary> public enum JhThreadStatus { Stop, //停止 Running, //正在運(yùn)行 Exit //已退出 } /// <summary> /// 線程狀態(tài)參數(shù) /// </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> /// 上下文對(duì)象 /// </summary> public object ObjParm { get { return objParm; } set { objParm = value; } } /// <summary> /// 控制狀態(tài) /// </summary> public JhThreadStatus Status { get { return status; } set { status = value; } } }; /// <summary> /// 通訊數(shù)據(jù)處理接口 /// </summary> public interface IObserver { // // 數(shù)據(jù)處理入口 // void Deal(CommData cd);
// // 數(shù)據(jù)處理重載方法.如果不希望后面的處理者繼續(xù)處理數(shù)據(jù),,則返回true,否則返回false; // bool OnDeal(CommData cd);
// // 附加的自身初始化操作 // bool Init();
// // 提前初始化接口 // bool BeforeInit();
// // 初始化后處理接口 // bool AfterInit();
// // 刪除前處理接口 // bool BeforeExit();
// // 下一個(gè)觀察者 // IObserver Next { get; set; }
// // 上一個(gè)觀察者 // IObserver Prev { get; set; }
// // 添加觀察者到后面,如果已經(jīng)存在鏈表中則不做任何操作 // void Add(IObserver observer);
// // 插入觀察者到下一個(gè)觀察者的前面 // void Insert(IObserver observer); //刪除觀察者 void Remove(IObserver observer); //是否存在鏈表中 bool IsExist(IObserver observer); } /// <summary> /// 通訊數(shù)據(jù)處理類的基類,,只能派生 /// </summary> public abstract class Observer : IObserver { /// <summary> /// 數(shù)據(jù)處理入口. /// </summary> /// <param name="client">TcpClient類 實(shí)例</param> /// <param name="s">內(nèi)存數(shù)據(jù)流</param> public void Deal(CommData cd) { cd.Data.Position = 0; if (OnDeal(cd) == false) return ; if (next != null) { next.Deal(cd); } return ; }
/// <summary> /// 數(shù)據(jù)處理重載方法. /// </summary> /// <param name="client">TcpClient類 實(shí)例</param> /// <param name="s">內(nèi)存數(shù)據(jù)流</param> /// <returns>處理結(jié)果,如果不希望后面的處理者繼續(xù)處理數(shù)據(jù),,則返回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; } //下一個(gè)觀察者 IObserver next = null; public IObserver Next { get { return next; } set { next = value; } } //上一個(gè)觀察者 IObserver prev = null; public IObserver Prev { get { return prev; } set { prev = value; } } //添加觀察者 public void Add(IObserver observer) { if (this == observer) return;//已經(jīng)存在 if (next == null) { next = observer;//達(dá)到最底端 next.Prev = this; } else next.Add(observer);//加到后面 } /// <summary> /// 插入觀察者到下一個(gè)觀察者的前面 /// </summary> /// <param name="observer"></param> public void Insert(IObserver observer) { //是否等于自己 if (this == observer) return; //先查找是否已經(jīng)存在鏈表中 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> /// 日志處理基類,,本身從通訊數(shù)據(jù)處理類的基類派生,。 /// </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> /// 數(shù)據(jù)集中管理類 /// </summary> public class CommDataMgr { static int index = 0; int id; /// <summary> /// 無參數(shù)構(gòu)造方法 /// </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> /// 析構(gòu)方法 /// </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("分發(fā)線程{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> /// 觀察者根節(jié)點(diǎn)類 定義 /// </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> /// 未處理數(shù)據(jù)個(gè)數(shù) /// </summary> public int DataCount { get { return aData.Count; } } /// <summary> /// 根據(jù)索引返回未處理數(shù)據(jù) /// </summary> internal CommData this[int Index] { get { return (CommData)aData[Index]; } } /// <summary> /// 根據(jù)索引刪除數(shù)據(jù) /// </summary> /// <param name="Index">索引</param> public void RemoveAt(int Index) { if (Index >= 0 && Index < DataCount) { lock (this) { aData.RemoveAt(Index); } } } /// <summary> /// 接收到新的數(shù)據(jù)提交 /// </summary> /// <param name="client">客戶端連接</param> /// <param name="s">數(shù)據(jù)流</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); } } // 取觀察者個(gè)數(shù) // 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> /// 內(nèi)部通信消息 /// </summary> enum JhCommMessages { MessageStart = 9909,//消息起始 DataTransfer, //數(shù)據(jù)傳輸 Disconnected, //連接將要斷開 ConnectSignal, //連接檢查信號(hào) ConnectCheck, //啟動(dòng)連接信號(hào) StopCheck, //停止連接信號(hào) Unknown = 9999 //未知 } /// <summary> /// 通信數(shù)據(jù) /// </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> /// 內(nèi)存數(shù)據(jù)流 /// </summary> public MemoryStream Data { get { return data; } set { data = value; } } /// <summary> /// 數(shù)據(jù)長度 /// </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> /// 連接關(guān)閉事件 /// </summary> public event CommEventHandler OnClosed; /// <summary> /// 連接失敗事件 /// </summary> public event CommEventHandler OnConnectFailed; /// <summary> /// 構(gòu)造方法 /// </summary> /// <param name="dm">外部植入的數(shù)據(jù)管理類</param> /// <param name="ob">觀察者</param> /// <param name="tcpClient">通信連接</param> public JhClient(CommDataMgr dm,IObserver ob,TcpClient tcpClient) { // // TOD 在此處添加構(gòu)造函數(shù)邏輯 // 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> /// 無參數(shù)構(gòu)造函數(shù) /// </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> /// 析構(gòu)方法 /// </summary> ~JhClient() { AutoConnect = false; ConnectCheck = false; Close(); Console.WriteLine("JH tcp client {0} unconstructed",ID); } Parm status = null; /// <summary> /// 唯一標(biāo)志符 /// </summary> int id = -1; public int ID { get { return id; } set { id = value; } } /// <summary> /// 連接狀態(tài) /// </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("連接已經(jīng)斷開!")); } } } /// <summary> /// 嘗試連接次數(shù) /// </summary> int connectTimes = 0; /// <summary> /// 讀取數(shù)據(jù)線程 /// </summary> Thread readThread = null; /// <summary> /// 自動(dòng)斷線重連標(biāo)志 /// </summary> bool autoConnect = false; /// <summary> /// 自動(dòng)斷線重連標(biāo)志 /// </summary> public bool AutoConnect { get { return autoConnect; } set { autoConnect = value; if (autoConnect != true) { lock(this) { autoConnectStatus.Status = JhThreadStatus.Stop; } } } }
/// <summary> /// 自動(dòng)連接間隔毫秒數(shù) /// </summary> int autoConnectInterval = 3000; /// <summary> /// 自動(dòng)連接間隔毫秒數(shù) /// </summary> public int AutoConnectInterval { get { return autoConnectInterval; } set { autoConnectInterval = value; } } /// <summary> /// 連接檢測(cè)的狀態(tài)控制 /// </summary> Parm checkStatus = null; /// <summary> /// 自動(dòng)連接的狀態(tài)控制 /// </summary> Parm autoConnectStatus = null; /// <summary> /// 連接監(jiān)測(cè)標(biāo)志 /// </summary> bool connectCheck = false; /// <summary> /// 連接監(jiān)測(cè)標(biāo)志 /// </summary> public bool ConnectCheck { get { return connectCheck; } set { bool b = value; if (connectCheck != b) { if (connectCheck != true)//啟動(dòng)檢測(cè) { lock(this) { checkStatus.Status = JhThreadStatus.Stop; } if (Connected == true) { SendMessage(JhCommMessages.StopCheck); } } else { if (Connected == true) StartConnectCheckThread(); } } } } /// <summary> /// 啟動(dòng)連接檢測(cè)線程 /// </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> /// 連接關(guān)閉事件響應(yīng) /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public virtual void OnConnectClosed(object sender,CommEventArgs e) { if (AutoConnect == true)//是否自動(dòng)重連 { StartAutoConnectThread(); } } /// <summary> /// 啟動(dòng)自動(dòng)重連線程 /// </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> /// 最近一次通訊時(shí)間 /// </summary> DateTime lastReceivedTime = DateTime.Now; /// <summary> /// 最近一次通訊時(shí)間 /// </summary> public DateTime LastReceivedTime { get { return lastReceivedTime; } set { lastReceivedTime = value; } } /// <summary> /// 連接檢測(cè)斷開判斷的最大允許毫秒數(shù) /// </summary> TimeSpan checkTimeout = new TimeSpan(1800000000);//3 minutes /// <summary> /// 連接檢測(cè)斷開判斷的最大允許毫秒數(shù) /// </summary> public TimeSpan CheckTimeout { get { return checkTimeout; } set { TimeSpan ts = value; if (ts.Minutes > 2) checkTimeout = ts;//檢查時(shí)間間隔不小于2分鐘 } } /// <summary> /// 自動(dòng)連接線程 /// </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> /// 連接檢測(cè)線程 /// </summary> void ConnectCheckThread() { try { while (checkStatus.Status == JhThreadStatus.Running) { if (Connected == true) { TimeSpan ts = DateTime.Now - lastReceivedTime; TimeSpan ts2 = CheckTimeout + CheckTimeout; if (ts > ts2 )//超過兩倍間隔時(shí)間,,認(rèn)為已經(jīng)斷開 { 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> /// 讀取數(shù)據(jù)的線程 /// </summary> void DataReadThread() { try { while (status.Status == JhThreadStatus.Running) { if (Connected == true) { NetworkStream ns = Client.GetStream(); int readCount,totalRead = 0; while (ns.DataAvailable == true)//讀取數(shù)據(jù),轉(zhuǎn)存到s中,,因?yàn)镹etworkStream的數(shù)據(jù)只能向前讀取一次 { readCount = ns.Read(buffer, 0, bufferSize); if (readCount > 0) { buf.Write(buffer, 0, readCount); totalRead += readCount; } else { break; } } ; if (totalRead > 0)//有數(shù)據(jù) { 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> /// 服務(wù)器ip /// </summary> string ipString; /// <summary> /// 服務(wù)器端口 /// </summary> int tcpPort; /// <summary> /// 根據(jù)當(dāng)前設(shè)置的ip和 port參數(shù)進(jìn)行連接 /// </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("已經(jīng)與服務(wù)器建立連接!")); } } catch(Exception le) { if (OnConnectFailed != null) OnConnectFailed(this,new CommEventArgs("第" + connectTimes.ToString() + "次與服務(wù)器建立連接失敗!" + le.Message)); } } /// <summary> /// 連接服務(wù)器 /// </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> /// 發(fā)送數(shù)據(jù) /// </summary> /// <param name="data"></param> /// <returns></returns> public void Send(string data) { Send( data, System.Text.Encoding.Default); } /// <summary> /// 發(fā)送數(shù)據(jù) /// </summary> /// <param name="data"></param> /// <returns></returns> public void Send(string data, System.Text.Encoding encodingway) { byte[] dt = encodingway.GetBytes(data); Send(dt); } /// <summary> /// 發(fā)送數(shù)據(jù) /// </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("尚未建立連接或者連接已經(jīng)斷開!"); } }
/// <summary> /// 關(guān)閉連接 /// </summary> public void Close() { if (Connected == true) { SendMessage(JhCommMessages.Disconnected); Connected = false; adm.Stop(); Client.Close(); Client = null; } } /// <summary> /// 程序退出時(shí)調(diào)用,,或者設(shè)置AutoConnect = false /// </summary> public void Exit() { AutoConnect = false; ConnectCheck = false; Close(); } /// <summary> /// TCP客戶對(duì)象 /// </summary> TcpClient client = null; /// <summary> /// TCP客戶對(duì)象 /// </summary> public TcpClient Client { get { return client; } set { client = value; } } /// <summary> /// 緩存未處理的數(shù)據(jù) /// </summary> MemoryStream buf = new MemoryStream(); /// <summary> /// 讀取接收到的數(shù)據(jù)的緩沖區(qū)的大小 /// </summary> const int bufferSize = 1024; /// <summary> /// 讀取接收到的數(shù)據(jù)的緩沖區(qū) /// </summary> byte[] buffer = new byte[bufferSize]; /// <summary> /// 數(shù)據(jù)分發(fā)管理者 /// </summary> CommDataMgr adm ; /// <summary> /// 數(shù)據(jù)分發(fā)管理者 /// </summary> public CommDataMgr DataMgr { set { adm = value; } } /// <summary> /// 接收到的數(shù)據(jù)的處理 /// </summary> private void DealData() { // if (buf.Length > 0) //有數(shù)據(jù)需要處理 { CommHead chio = new CommHead(buf,(int)buf.Position); if (chio.IsValid()) { LastReceivedTime = DateTime.Now; if (chio.DataLen > 0)//有效數(shù)據(jù) { adm.AddData(this,chio.GetData(),chio.DataLen);//可處理數(shù)據(jù) } else//純內(nèi)部消息 { switch ((JhCommMessages)chio.WParam) { case JhCommMessages.Disconnected: //對(duì)方將要斷開連接消息 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);//剩下未處理完數(shù)據(jù) } } } /// <summary> /// 不帶參數(shù)的消息 /// </summary> /// <param name="message"></param> private void SendMessage(JhCommMessages message) { SendMessage(message,0); } /// <summary> /// 帶參數(shù)的消息 /// </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通信服務(wù)器類 /// </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監(jiān)聽對(duì)象 /// </summary> TcpListener server = null;
/// <summary> /// 客戶端序號(hào) /// </summary> int clientindex = 0;
/// <summary> /// 開始監(jiān)聽 /// </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> /// 監(jiān)聽線程 /// </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> /// 發(fā)送數(shù)據(jù) /// </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> /// 用最后一個(gè)客戶端發(fā)送數(shù)據(jù) /// </summary> /// <param name="data"></param> public void Send(string data) { Send(GetClient(clients.Count - 1),data); }
/// <summary> /// 數(shù)據(jù)分發(fā)管理者 /// </summary> CommDataMgr adm ;
Parm status = null;
/// <summary> /// 客戶連接線程 /// </summary> void ListenThread() { try { while (status.Status == JhThreadStatus.Running) { if (server.Pending() == true) { TcpClient client = server.AcceptTcpClient();//偵聽到連接后創(chuàng)建客戶端 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> /// 根據(jù)內(nèi)部id獲取客戶端 /// </summary> /// <param name="id"></param> /// <returns></returns> public JhClient GetClient(int id) { return (JhClient)clients[id]; }
/// <summary> /// 設(shè)置客戶端對(duì)象 /// </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;// 頭結(jié)構(gòu)長度 Int16 wFlag;//合法數(shù)據(jù)包特征字 Int16 wVer;// 用版本號(hào)表示標(biāo)識(shí)符 Int16 wParm;// 參數(shù)一 Int32 dwParm;// 參數(shù)二 Int32 dwDataLen;// 后續(xù)數(shù)據(jù)長度
/// <summary> /// 新建頭構(gòu)造方法 /// </summary> public CommHead() : this(System.Text.Encoding.Default) { Init(); }
/// <summary> /// 新建頭構(gòu)造方法 /// </summary> public CommHead(System.Text.Encoding enCoding) { encoding = enCoding; Init(); }
System.Text.Encoding encoding; /// <summary> /// 解析數(shù)據(jù)構(gòu)造方法 /// </summary> /// <param name="s">數(shù)據(jù)流</param> public CommHead(MemoryStream s,int len) : this(s,len,System.Text.Encoding.Default) { }
/// <summary> /// 解析數(shù)據(jù)構(gòu)造方法 /// </summary> /// <param name="s">數(shù)據(jù)流</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; }
// 當(dāng)前頭數(shù)據(jù)是否有效 public bool IsValid() {return wFlag == 0x4a48 && wHeadSize == 16; }
// 返回雙字節(jié)參數(shù) public Int32 DWParam { get { return dwParm; } set { dwParm = value; } }
// 返回單字節(jié)參數(shù) public Int16 WParam { get { return wParm; } set { wParm = value; } }
// 返回頭結(jié)構(gòu)大小 public Int16 HeadSize { get { return wHeadSize; } }
// 返回版本標(biāo)識(shí)符 public virtual Int16 Ver { get { return wVer; } }
// 返回后續(xù)數(shù)據(jù)長度 public virtual Int32 DataLen { get { return dwDataLen; } set { dwDataLen = value; } }
/// <summary> /// 返回未處理數(shù)據(jù) /// </summary> /// <returns></returns> public void GetLeftData(ref MemoryStream s) { if (moreData != null) { moreData.WriteTo(s); moreData.Close(); } }
/// <summary> /// 返回完整數(shù)據(jù) /// </summary> /// <returns></returns> public MemoryStream GetData() { return recvData; }
/// <summary> /// 添加數(shù)據(jù) /// </summary> /// <param name="pszData"></param> public void Add(byte[] pszData) { data.Write(pszData,0,pszData.Length); dwDataLen += pszData.Length; } MemoryStream data = new MemoryStream();
/// <summary> /// 需要發(fā)送的數(shù)據(jù)轉(zhuǎn)為字節(jié)數(shù)組 /// </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> /// 需要發(fā)送的數(shù)據(jù)的長度 /// </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; } }
|