完整的TCP通信包实现

类别:.NET开发 点击:0 评论:0 推荐:

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)
  {
   //
   // TODO: 在此处添加构造函数逻辑
   //
   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;
 }
}

本文地址:http://com.8s8s.com/it/it41874.htm