zoukankan      html  css  js  c++  java
  • Tcp 数据对象传输接口对象设计

    输入是一个对象inputObj,接口对象.Send(inputObj),对端接收之后解包成outputObj(与inputObj应相同),触发onPackageReceive事件

    • 事件

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

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

    •  成员

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

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

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

             Send()//发送数据对象

      1 public class draftClass
      2     {
      3         #region Structure
      4         #endregion
      5 
      6         #region Fields
      7         object locker;
      8         TcpClient clientObj;
      9         Messager messager=new Messager();
     10         Thread recvThread;
     11         #endregion
     12 
     13         #region Events        
     14         public delegate void DataServiceHandler(string msg,object sender);
     15         public event DataServiceHandler onPackageReceived;
     16         public event DataServiceHandler onPackageSent;
     17         public event DataServiceHandler onPeerDisconnected;
     18         public event DataServiceHandler onSendingException;
     19         public event DataServiceHandler onReceivingException;
     20         public event DataServiceHandler onNotify;
     21         #endregion
     22 
     23         #region Functions
     24         public void SetClient(TcpClient tc)
     25         {
     26             Stop();
     27             clientObj = tc;
     28             StartReceiving();
     29         }
     30         public void ReStart()
     31         {
     32             SetClient(this.clientObj);
     33         }
     34         public void Stop() { lock (recvThread) { recvThread.Abort(); } }
     35 
     36         /// <summary>
     37         /// 打包msg和数据对象,并发送
     38         /// </summary>
     39         /// <param name="msg"></param>
     40         /// <param name="o"></param>
     41         public void Send(string msg, object o)
     42         {
     43             byte[] m = new byte[100];
     44             Encoding.UTF8.GetBytes(msg).CopyTo(m, 0);
     45             byte[] data = ObjectToBytes(o);
     46             byte[] d = new byte[m.Length + data.Length];
     47             m.CopyTo(d, 0);
     48             data.CopyTo(d, m.Length);
     49 
     50             Send(this.clientObj.GetStream(), d);
     51         }
     52         public void StartReceiving()
     53         {
     54             Thread t = new Thread(new ThreadStart(Receiving));
     55             t.Name = "[DataService] Receiving Thread";
     56             t.Start();
     57         }
     58 
     59         private void Send(NetworkStream ns, byte[] d)
     60         {
     61             lock (this)
     62             {
     63                 NetworkStream netStream = ns;
     64                 byte[] data = new byte[d.Length + 4];
     65                 System.BitConverter.GetBytes(d.Length).CopyTo(data, 0);
     66                 d.CopyTo(data, 4);
     67 
     68                 netStream.Write(data, 0, data.Length);
     69             }
     70         }
     71         private void Receiving()
     72         {
     73             {
     74                 Console.WriteLine("In Thread({0}),WaitingData", Thread.CurrentThread.ManagedThreadId);
     75                 NetworkStream ns = clientObj.GetStream();
     76                 while (IsOnline())
     77                 {
     78                     while (ns.DataAvailable)
     79                     {
     80 #if DEBUG
     81                         DateTime start = DateTime.Now;
     82 #endif
     83                         //收到的数据为2进制的原始数据,数据交给分发器处理函数
     84                         byte[] data = ReceiveByteArray(ns);
     85                         Distributor(data);
     86 #if DEBUG
     87                         TimeSpan ts = DateTime.Now - start;
     88                         double r = data.Length * 8 / (ts.TotalSeconds * 1024 * 1024);
     89                         Console.WriteLine("ReceiveByteArray Length={0}	During={1:f0}ms	Rate= {2:f3} Mbps", data.Length, ts.TotalMilliseconds, r);
     90 #endif
     91                     }
     92                     //Thread.Sleep(3);
     93                 }
     94                 Console.WriteLine("In Thread({0}),clientObj Disconnect!", Thread.CurrentThread.ManagedThreadId);
     95 
     96                 if (onPeerDisconnected != null)
     97                     onPeerDisconnected("Peer Disconnected",null);
     98                 Thread.CurrentThread.Abort();
     99             }
    100         }
    101         //报文结构是自定义的2进制数据
    102         //Part1:定长100字节,存放消息
    103         //Part2:序列化了的数据对象
    104         private void Distributor(byte[] data)
    105         {
    106             //解包
    107             string msg = GetMsg(data);
    108             object obj = GetObj(data);
    109 
    110             //msg过Messager.Paser()
    111             if (messager.TryParser(msg, obj))
    112                 return;
    113 
    114             //如果Messager处理失败,触发onPackageReceived事件
    115             if (onPackageReceived != null)
    116                 onPackageReceived("",data);
    117         }
    118         #region api 
    119         private string GetMsg(byte[] data) { return ""; }
    120         private object GetObj(byte[] data) {return new object(); }
    121         private byte[] ReceiveByteArray(NetworkStream stream)
    122         {
    123             try
    124             {
    125                 int bufferlen = GetSize(stream);
    126                 byte[] resultbyte = new byte[bufferlen];
    127 
    128                 int offset = 0, bytesread = 0;
    129                 while (offset < bufferlen)
    130                 {
    131                     bytesread = stream.Read(resultbyte, offset, bufferlen - offset);
    132                     if (bytesread == 0)
    133                     {
    134                         Console.WriteLine("?????A");
    135                         throw new Exception("网络异常断开,数据读取不完整。");
    136                     }
    137                     else
    138                         offset += bytesread;
    139                 }
    140                 return resultbyte;
    141             }
    142             catch (Exception)
    143             {
    144                 Console.WriteLine("?????B");
    145                 throw;
    146             }
    147         }
    148         private int GetSize(NetworkStream stream)
    149         {
    150             try
    151             {
    152                 int bufferlen = 4;
    153                 byte[] resultbyte = new byte[bufferlen];
    154 
    155                 int offset = 0, bytesread = 0;
    156                 while (offset < bufferlen)
    157                 {
    158                     bytesread = stream.Read(resultbyte, offset, bufferlen - offset);
    159                     if (bytesread == 0)
    160                         throw new Exception("网络异常断开,数据读取不完整。");
    161                     else
    162                         offset += bytesread;
    163                 }
    164                 return System.BitConverter.ToInt32(resultbyte, 0);
    165             }
    166             catch (Exception)
    167             {
    168                 throw;
    169             }
    170         }
    171         private bool IsOnline()
    172         {
    173             TcpClient c = this.clientObj;
    174             return !((c.Client.Poll(1000, SelectMode.SelectRead) && (c.Client.Available == 0)) || !c.Client.Connected);
    175         }
    176         /// <summary> 
    177         /// 将一个object对象序列化,返回一个byte[]         
    178         /// </summary> 
    179         /// <param name="obj">能序列化的对象</param>         
    180         /// <returns></returns> 
    181         /// 
    182         private byte[] ObjectToBytes(object obj)
    183         {
    184             using (MemoryStream ms = new MemoryStream())
    185             {
    186                 IFormatter formatter = new BinaryFormatter(); formatter.Serialize(ms, obj); return ms.GetBuffer();
    187             }
    188         }
    189         /// <summary> 
    190         /// 将一个序列化后的byte[]数组还原         
    191         /// </summary>
    192         /// <param name="Bytes"></param>         
    193         /// <returns></returns> 
    194         private object BytesToObject(byte[] Bytes)
    195         {
    196             using (MemoryStream ms = new MemoryStream(Bytes))
    197             {
    198                 IFormatter formatter = new BinaryFormatter(); return formatter.Deserialize(ms);
    199             }
    200         }
    201         #endregion
    202         #endregion
    203     }
    DataService.cs
  • 相关阅读:
    弄明白python reduce 函数
    Python 2与Python 3兼容性的写法,需要一个特殊的包 from __future__ import print_function 用法
    人工智能数学参考---8、常用激活函数
    常用激活函数(激励函数)理解与总结
    人工智能数学参考---7、核函数应用
    [粘贴]环绕闸极不能让三星在3nm工艺领先台积电
    查看java所有的线程信息
    【转载】 Sqlserver使用Left函数从最左边开始截取固定长度字符串
    值初始化和默认初始化的区别
    map的综合例子
  • 原文地址:https://www.cnblogs.com/xiaoboz/p/4736689.html
Copyright © 2011-2022 走看看