zoukankan      html  css  js  c++  java
  • 完整的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)
    {
    //
    // 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;
    }
    }
  • 相关阅读:
    C语言高效编程的几招
    部分功能函数命名总结(补充中)
    Linux的多线程编程的高效开发经验
    生成PDF下载 HTTP或FTP远程获取PDF
    .dnn文件 xml 配置
    有身体 有钱 还要有什么能进太空?
    dnn 4.8.2 RegisterStartupScript 函数失效 解决方案
    字符串 分隔符 逗号行吗? JAVASCRIPT 函数参数中有单双引号
    2007年的最后一天,最后一个小时。
    标题中有单引号',怎么查询?
  • 原文地址:https://www.cnblogs.com/zhuor/p/308924.html
Copyright © 2011-2022 走看看