【转】c#中关于udp实现可靠地传输(数据包的分组发送)

转自:http://blog.csdn.net/zhujunxxxxx/article/details/18798431?utm_source=tuicool

在做c#中面向无连接的传输时用到了UDP,虽然没有TCP稳定可靠。但是效率是要高些,优势也有,缺点也有

就是有的时候要丢包,有的时候不得不用UDP,但是如何才能比较稳定的实现可靠传输呢,这是一个问题。

TCP传输数据的时候没有大小限制,但是UDP传输的时候是有大小限制的,我们怎么才能够实现大数据的稳定传输呢。我们想到了,把数据包分包。

把一个大数据分割为一系列的小数据包然后分开发送,然后服务端收到了就拼凑起完整数据。

如果遇到中途丢包就重发。

UDP线程类,实现数据的分包发送和重发。具体的接收操作需要实现其中的事件

[csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Net.Sockets;  
  6. using Model;  
  7. using System.Net;  
  8. using Tool;  
  9. using System.Threading;  
  10.   
  11. namespace ZZUdp.Core  
  12. {  
  13.     //udp的类    
  14.     public class UDPThread  
  15.     {  
  16.         #region 私有变量  
  17.   
  18.         UdpClient client;//UDP客户端  
  19.   
  20.         List<UdpPacket> sendlist;// 用于轮询是否发送成功的记录  
  21.   
  22.         Dictionary<long, RecDataList> RecListDic = new Dictionary<long, RecDataList>();//数据接收列表,每一个sequence对应一个  
  23.   
  24.         IPEndPoint remotIpEnd = null;//用来在接收数据的时候对远程主机的信息存放  
  25.   
  26.         int port=6666;//定义服务器的端口号  
  27.         #endregion  
  28.  
  29.         #region 属性  
  30.         public int CheckQueueTimeInterval { getset; }//检查发送队列间隔  
  31.   
  32.         public int MaxResendTimes { getset; }//没有收到确认包时,最大重新发送的数目,超过此数目会丢弃并触发PackageSendFailture事件  
  33.         #endregion  
  34.  
  35.         #region 事件  
  36.           
  37.         /// <summary>  
  38.         /// 当数据包收到时触发  
  39.         /// </summary>  
  40.         public event EventHandler<PackageEventArgs> PackageReceived;  
  41.         /// <summary>  
  42.         /// 当数据包收到事件触发时,被调用  
  43.         /// </summary>  
  44.         /// <param name="e">包含事件的参数</param>  
  45.         protected virtual void OnPackageReceived(PackageEventArgs e)  
  46.         {  
  47.             if (PackageReceived != null)   
  48.                 PackageReceived(this, e);  
  49.         }  
  50.   
  51.         /// <summary>  
  52.         /// 数据包发送失败  
  53.         /// </summary>  
  54.         public event EventHandler<PackageEventArgs> PackageSendFailure;  
  55.         /// <summary>  
  56.         /// 当数据发送失败时调用  
  57.         /// </summary>  
  58.         /// <param name="e">包含事件的参数</param>  
  59.         protected virtual void OnPackageSendFailure(PackageEventArgs e)  
  60.         {  
  61.             if (PackageSendFailure != null)   
  62.                 PackageSendFailure(this, e);  
  63.         }  
  64.   
  65.         /// <summary>  
  66.         /// 数据包未接收到确认,重新发送  
  67.         /// </summary>  
  68.         public event EventHandler<PackageEventArgs> PackageResend;  
  69.         /// <summary>  
  70.         /// 触发重新发送事件  
  71.         /// </summary>  
  72.         /// <param name="e">包含事件的参数</param>  
  73.         protected virtual void OnPackageResend(PackageEventArgs e)  
  74.         {  
  75.             if (PackageResend != null)   
  76.                 PackageResend(this, e);  
  77.         }  
  78.         #endregion  
  79.   
  80.   
  81.         //无参构造函数  
  82.         public UDPThread()  
  83.         {   
  84.         }  
  85.         //构造函数  
  86.         public UDPThread(string ipaddress, int port)  
  87.         {  
  88.             IPAddress ipA = IPAddress.Parse(ipaddress);//构造远程连接的参数  
  89.             IPEndPoint ipEnd = new IPEndPoint(ipA, port);  
  90.             client = new UdpClient();// client = new UdpClient(ipEnd)这样的话就没有创建远程连接  
  91.             client.Connect(ipEnd);//使用指定的远程主机信息建立默认远程主机连接  
  92.             sendlist = new List<UdpPacket>();  
  93.   
  94.             CheckQueueTimeInterval = 2000;//轮询间隔时间  
  95.             MaxResendTimes = 5;//最大发送次数  
  96.               
  97.             new Thread(new ThreadStart(CheckUnConfirmedQueue)) { IsBackground = true }.Start();//启动轮询线程  
  98.             //开始监听数据  
  99.             AsyncReceiveData();  
  100.         }  
  101.         /// <summary>  
  102.         /// 同步数据接收方法  
  103.         /// </summary>  
  104.         public void ReceiveData()  
  105.         {  
  106.             while (true)  
  107.             {  
  108.                 IPEndPoint retip = null;  
  109.                 UdpPacket udpp = null;  
  110.                 try  
  111.                 {  
  112.                     byte[] data = client.Receive(ref retip);//接收数据,当Client端连接主机的时候,retip就变成Cilent端的IP了  
  113.                     udpp = (UdpPacket)SerializationUnit.DeserializeObject(data);  
  114.                 }  
  115.                 catch (Exception ex)  
  116.                 {  
  117.                     //异常处理操作  
  118.                 }  
  119.                 if (udpp != null)  
  120.                 {  
  121.                     PackageEventArgs arg = new PackageEventArgs(udpp, retip);  
  122.                     OnPackageReceived(arg);//数据包收到触发事件  
  123.                 }  
  124.             }  
  125.         }  
  126.   
  127.         //异步接受数据  
  128.         public void AsyncReceiveData()  
  129.         {  
  130.             try  
  131.             {  
  132.                 client.BeginReceive(new AsyncCallback(ReceiveCallback), null);  
  133.             }  
  134.             catch (SocketException ex)  
  135.             {  
  136.                 throw ex;  
  137.             }  
  138.         }  
  139.         //接收数据的回调函数  
  140.         public void ReceiveCallback(IAsyncResult param)  
  141.         {  
  142.             if (param.IsCompleted)  
  143.             {  
  144.                 UdpPacket udpp = null;  
  145.                 try  
  146.                 {  
  147.                     byte[] data = client.EndReceive(param, ref remotIpEnd);//接收数据,当Client端连接主机的时候,test就变成Cilent端的IP了  
  148.                     udpp = (UdpPacket)SerializationUnit.DeserializeObject(data);  
  149.                 }  
  150.                 catch (Exception ex)  
  151.                 {  
  152.                     //异常处理操作  
  153.                 }  
  154.                 finally  
  155.                 {  
  156.                     AsyncReceiveData();  
  157.                 }  
  158.                 if (udpp != null)//触发数据包收到事件  
  159.                 {  
  160.                     PackageEventArgs arg = new PackageEventArgs(udpp, null);  
  161.                     OnPackageReceived(arg);  
  162.                 }  
  163.             }  
  164.         }  
  165.   
  166.   
  167.         /// <summary>  
  168.         /// 同步发送分包数据  
  169.         /// </summary>  
  170.         /// <param name="message"></param>  
  171.         public void SendData(Msg message)  
  172.         {  
  173.              
  174.             ICollection<UdpPacket> udpPackets = UdpPacketSplitter.Split(message);  
  175.             foreach (UdpPacket udpPacket in udpPackets)  
  176.             {  
  177.                 byte[] udpPacketDatagram = SerializationUnit.SerializeObject(udpPacket);  
  178.                 //使用同步发送  
  179.                client.Send(udpPacketDatagram, udpPacketDatagram.Length,udpPacket.remoteip);  
  180.                if (udpPacket.IsRequireReceiveCheck)  
  181.                    PushSendItemToList(udpPacket);//将该消息压入列表  
  182.   
  183.             }  
  184.         }  
  185.           
  186.         /// <summary>  
  187.         /// 异步分包发送数组的方法  
  188.         /// </summary>  
  189.         /// <param name="message"></param>  
  190.         public void AsyncSendData(Msg message)  
  191.         {  
  192.               
  193.             ICollection<UdpPacket> udpPackets = UdpPacketSplitter.Split(message);  
  194.             foreach (UdpPacket udpPacket in udpPackets)  
  195.             {  
  196.                 byte[] udpPacketDatagram = SerializationUnit.SerializeObject(udpPacket);  
  197.                 //使用同步发送  
  198.                 //client.Send(udpPacketDatagram, udpPacketDatagram.Length);  
  199.   
  200.                 //使用异步的方法发送数据  
  201.                 this.client.BeginSend(udpPacketDatagram, udpPacketDatagram.Length, new AsyncCallback(SendCallback), null);  
  202.   
  203.             }  
  204.         }  
  205.         //发送完成后的回调方法  
  206.         public void SendCallback(IAsyncResult param)  
  207.         {  
  208.             if (param.IsCompleted)  
  209.             {  
  210.                 try  
  211.                 {  
  212.                     client.EndSend(param);//这句话必须得写,BeginSend()和EndSend()是成对出现的   
  213.                 }  
  214.                 catch (Exception e)  
  215.                 {  
  216.                     //其他处理异常的操作  
  217.                 }  
  218.             }  
  219.   
  220.         }  
  221.         static object lockObj = new object();  
  222.         /// <summary>  
  223.         /// 自由线程,检测未发送的数据并发出,存在其中的就是没有收到确认包的数据包  
  224.         /// </summary>  
  225.         void CheckUnConfirmedQueue()  
  226.         {  
  227.             do  
  228.             {  
  229.                 if (sendlist.Count > 0)  
  230.                 {  
  231.                     UdpPacket[] array = null;  
  232.   
  233.                     lock (sendlist)  
  234.                     {  
  235.                         array = sendlist.ToArray();  
  236.                     }  
  237.                     //挨个重新发送并计数  
  238.                     Array.ForEach(array, s =>  
  239.                     {  
  240.                         s.sendtimes++;  
  241.                         if (s.sendtimes >= MaxResendTimes)  
  242.                         {  
  243.                             //sOnPackageSendFailure//出发发送失败事件  
  244.                             sendlist.Remove(s);//移除该包  
  245.                         }  
  246.                         else  
  247.                         {  
  248.                             //重新发送  
  249.                             byte[] udpPacketDatagram = SerializationUnit.SerializeObject(s);  
  250.                             client.Send(udpPacketDatagram, udpPacketDatagram.Length, s.remoteip);  
  251.                         }  
  252.                     });  
  253.                 }  
  254.   
  255.                Thread.Sleep(CheckQueueTimeInterval);//间隔一定时间重发数据  
  256.             } while (true);  
  257.         }  
  258.         /// <summary>  
  259.         /// 将数据信息压入列表  
  260.         /// </summary>  
  261.         /// <param name="item"></param>  
  262.         void PushSendItemToList(UdpPacket item)  
  263.         {  
  264.             sendlist.Add(item);  
  265.         }  
  266.         /// <summary>  
  267.         /// 将数据包从列表中移除  
  268.         /// </summary>  
  269.         /// <param name="packageNo">数据包编号</param>  
  270.         /// <param name="packageIndex">数据包分包索引</param>  
  271.         public void PopSendItemFromList(long packageNo, int packageIndex)  
  272.         {  
  273.             lock (lockObj)  
  274.             {  
  275.                 Array.ForEach(sendlist.Where(s => s.sequence == packageNo && s.index == packageIndex).ToArray(), s => sendlist.Remove(s));  
  276.             }  
  277.         }  
  278.         /// <summary>  
  279.         /// 关闭客户端并释放资源  
  280.         /// </summary>  
  281.         public void Dispose()  
  282.         {  
  283.             if (client != null)  
  284.             {  
  285.                 client.Close();  
  286.                 client = null;  
  287.             }  
  288.         }  
  289.   
  290.   
  291.   
  292.     }  
  293. }  



首先是数据信息实体类

[csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Net;  
  6.   
  7. namespace Model  
  8. {  
  9.     //封装消息类  
  10.     [Serializable]  
  11.    public class Msg  
  12.     {  
  13.         //所属用户的用户名  
  14.         public string name { getset; }  
  15.   
  16.         //所属用户的ip  
  17.         public string host { getset; }  
  18.   
  19.         //命令的名称  
  20.         public string command { getset; }  
  21.   
  22.         //收信人的姓名  
  23.         public string desname { getset; }  
  24.   
  25.         //你所发送的消息的目的地ip,应该是对应在服务器的列表里的主键值  
  26.         public string destinationIP { getset; }  
  27.   
  28.         //端口号  
  29.         public int port { getset; }  
  30.   
  31.         //文本消息  
  32.         public string msg { getset; }  
  33.   
  34.         //二进制消息  
  35.         public byte[] byte_msg { getset; }  
  36.   
  37.         //附加数据  
  38.         public string extend_msg { getset; }  
  39.   
  40.         //时间戳  
  41.         public DateTime time { getset; }  
  42.   
  43.         //构造函数  
  44.         public Msg(string command,string desip,string msg,string host)  
  45.         {  
  46.             this.command = command;  
  47.             this.destinationIP = desip;  
  48.             this.msg = msg;  
  49.             this.time = DateTime.Now;  
  50.             this.host = host;  
  51.         }  
  52.         override  
  53.         public string ToString()  
  54.         {  
  55.             return name + "说:" + msg;  
  56.         }  
  57.     }  
  58. }  

MSG数据分割后生成分包数据

分包实体类

[csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using Tool;  
  6. using System.Net;  
  7.   
  8. namespace Model  
  9. {  
  10.     [Serializable]  
  11.     public class UdpPacket  
  12.     {  
  13.         public long sequence{get;set;}//所属组的唯一序列号 包编号  
  14.         public int total { getset; }//分包总数  
  15.         public int index { getset; }//消息包的索引  
  16.         public byte[] data { getset; }//包的内容数组  
  17.         public int dataLength { getset; }//分割的数组包大小  
  18.         public int remainder { getset; }//最后剩余的数组的数据长度  
  19.         public int sendtimes { getset; }//发送次数  
  20.         public IPEndPoint remoteip { getset; }//接受该包的远程地址  
  21.         public bool IsRequireReceiveCheck { getset; }//获得或设置包收到时是否需要返回确认包  
  22.         public static int HeaderSize = 30000;  
  23.         public UdpPacket(long sequence, int total, int index, byte[] data, int dataLength, int remainder,string desip,int port)  
  24.         {  
  25.             this.sequence = sequence;  
  26.             this.total = total;  
  27.             this.index = index;  
  28.             this.data = data;  
  29.             this.dataLength = dataLength;  
  30.             this.remainder = remainder;  
  31.             this.IsRequireReceiveCheck = true;//默认都需要确认包  
  32.             //构造远程地址  
  33.             IPAddress ipA = IPAddress.Parse(desip);  
  34.             this.remoteip = new IPEndPoint(ipA, port);  
  35.         }  
  36.         //把这个对象生成byte[]  
  37.         public byte[] ToArray()  
  38.         {  
  39.             return SerializationUnit.SerializeObject(this);  
  40.         }  
  41.     }  
  42. }  

数据包分割工具类

[csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using Tool;  
  6.   
  7. namespace Model  
  8. {  
  9.         /// <summary>  
  10.         /// UDP数据包分割器  
  11.         /// </summary>  
  12.         public static class UdpPacketSplitter  
  13.         {  
  14.   
  15.   
  16.             public static ICollection<UdpPacket> Split(Msg message)  
  17.             {  
  18.                 byte[] datagram = null;  
  19.                 try  
  20.                 {  
  21.                     datagram = SerializationUnit.SerializeObject(message);  
  22.                 }  
  23.                 catch (Exception e)  
  24.                 {  
  25.                     //AddTalkMessage("数据转型异常");  
  26.                 }  
  27.                 //产生一个序列号,用来标识包数据属于哪一组  
  28.                 Random Rd = new Random();  
  29.                 long SequenceNumber = Rd.Next(88888, 999999);  
  30.                 ICollection<UdpPacket> udpPackets = UdpPacketSplitter.Split(SequenceNumber, datagram, 10240, message.destinationIP, message.port);  
  31.   
  32.                 return udpPackets;  
  33.             }  
  34.             /// <summary>  
  35.             /// 分割UDP数据包  
  36.             /// </summary>  
  37.             /// <param name="sequence">UDP数据包所持有的序号</param>  
  38.             /// <param name="datagram">被分割的UDP数据包</param>  
  39.             /// <param name="chunkLength">分割块的长度</param>  
  40.             /// <returns>  
  41.             /// 分割后的UDP数据包列表  
  42.             /// </returns>  
  43.             public static ICollection<UdpPacket> Split(long sequence, byte[] datagram, int chunkLength,string desip,int port)  
  44.             {  
  45.                 if (datagram == null)  
  46.                     throw new ArgumentNullException("datagram");  
  47.   
  48.                 List<UdpPacket> packets = new List<UdpPacket>();  
  49.   
  50.                 int chunks = datagram.Length / chunkLength;  
  51.                 int remainder = datagram.Length % chunkLength;  
  52.                 int total = chunks;  
  53.                 if (remainder > 0) total++;  
  54.   
  55.                 for (int i = 1; i <= chunks; i++)  
  56.                 {  
  57.                     byte[] chunk = new byte[chunkLength];  
  58.                     Buffer.BlockCopy(datagram, (i - 1) * chunkLength, chunk, 0, chunkLength);  
  59.                     packets.Add(new UdpPacket(sequence, total, i, chunk, chunkLength, remainder, desip, port));  
  60.                 }  
  61.                 if (remainder > 0)  
  62.                 {  
  63.                     int length = datagram.Length - (chunkLength * chunks);  
  64.                     byte[] chunk = new byte[length];  
  65.                     Buffer.BlockCopy(datagram, chunkLength * chunks, chunk, 0, length);  
  66.                     packets.Add(new UdpPacket(sequence, total, total, chunk, chunkLength, remainder, desip, port));  
  67.                 }  
  68.   
  69.                 return packets;  
  70.             }  
  71.         }  
  72. }  

服务端存储数据的数据结构

[csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using Tool;  
  6. using Model;  
  7.   
  8. namespace Model  
  9. {  
  10.     //一个sequence对应一组的数据包的数据结构  
  11.     public class RecDataList  
  12.     {  
  13.         public long sequence { getset; }//序列号  
  14.         //对应的存储包的List  
  15.         List<UdpPacket> RecudpPackets = new List<UdpPacket>();  
  16.         public int total { getset; }  
  17.         public int dataLength { getset; }  
  18.         public int remainder { getset; }  
  19.         public byte[] DataBuffer = null;  
  20.         public RecDataList(UdpPacket udp)  
  21.         {  
  22.   
  23.             this.sequence = udp.sequence;  
  24.             this.total = udp.total;  
  25.             this.dataLength = udp.dataLength;  
  26.             this.remainder = udp.remainder;  
  27.             if (DataBuffer == null)  
  28.             {  
  29.                 DataBuffer = new byte[dataLength * (total - 1) + remainder];  
  30.             }  
  31.         }  
  32.         public RecDataList(long sequence, int total, int chunkLength, int remainder)  
  33.         {  
  34.               
  35.             this.sequence = sequence;  
  36.             this.total = total;  
  37.             this.dataLength = chunkLength;  
  38.             this.remainder = remainder;  
  39.             if (DataBuffer == null)  
  40.             {  
  41.                 DataBuffer = new byte[this.dataLength * (this.total - 1) + this.remainder];  
  42.             }  
  43.         }  
  44.         public void addPacket(UdpPacket p)  
  45.         {  
  46.             RecudpPackets.Add(p);  
  47.         }  
  48.         public Msg show()   
  49.         {  
  50.             if (RecudpPackets.Count == total)//表示已经收集满了  
  51.             {  
  52.                 //重组数据  
  53.                 foreach (UdpPacket udpPacket in RecudpPackets)  
  54.                 {  
  55.                     //偏移量  
  56.                     int offset = (udpPacket.index - 1) * udpPacket.dataLength;  
  57.                     Buffer.BlockCopy(udpPacket.data, 0, DataBuffer, offset, udpPacket.data.Length);  
  58.                 }  
  59.                 Msg rmsg = (Msg)SerializationUnit.DeserializeObject(DataBuffer);  
  60.                 DataBuffer = null;  
  61.                 RecudpPackets.Clear();  
  62.                 return rmsg;  
  63.             }  
  64.             else  
  65.             {  
  66.                 return null;  
  67.             }  
  68.         }  
  69.         public bool containskey(UdpPacket udp)  
  70.         {  
  71.             foreach (UdpPacket udpPacket in RecudpPackets)  
  72.             {  
  73.                 if (udpPacket.index == udp.index)  
  74.                     return true;  
  75.             }  
  76.             return false;  
  77.         }  
  78.     }  
  79. }  

编码工具类

[csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Runtime.Serialization.Formatters.Binary;  
  6. using System.IO;  
  7.   
  8. namespace Tool  
  9. {  
  10.     public class EncodingTool  
  11.     {  
  12.         //编码  
  13.         public static byte[] EncodingASCII(string buf)  
  14.         {  
  15.             byte[] data = Encoding.Unicode.GetBytes(buf);  
  16.             return data;  
  17.         }  
  18.         //解码  
  19.         public static string DecodingASCII(byte[] bt)  
  20.         {  
  21.             string st = Encoding.Unicode.GetString(bt);  
  22.             return st;  
  23.         }  
  24.   
  25.   
  26.   
  27.         //编码  
  28.         public static byte[] EncodingUTF_8(string buf)  
  29.         {  
  30.             byte[] data = Encoding.UTF8.GetBytes(buf);  
  31.             return data;  
  32.         }  
  33.         //编码  
  34.         public static string DecodingUTF_8(byte[] bt)  
  35.         {  
  36.             string st = Encoding.UTF8.GetString(bt);  
  37.             return st;  
  38.         }  
  39.          
  40.     }  
  41. }  

序列化和反序列化的工具类

[csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Runtime.Serialization.Formatters.Binary;  
  6. using System.IO;  
  7. namespace Tool  
  8. {  
  9.   
  10.     public class SerializationUnit  
  11.     {  
  12.         /// <summary>    
  13.         /// 把对象序列化为字节数组    
  14.         /// </summary>    
  15.         public static byte[] SerializeObject(object obj)  
  16.         {  
  17.             if (obj == null)  
  18.                 return null;  
  19.             //内存实例  
  20.             MemoryStream ms = new MemoryStream();  
  21.             //创建序列化的实例  
  22.             BinaryFormatter formatter = new BinaryFormatter();  
  23.             formatter.Serialize(ms, obj);//序列化对象,写入ms流中    
  24.             ms.Position = 0;  
  25.             //byte[] bytes = new byte[ms.Length];//这个有错误  
  26.             byte[] bytes = ms.GetBuffer();  
  27.             ms.Read(bytes, 0, bytes.Length);  
  28.             ms.Close();  
  29.             return bytes;  
  30.         }  
  31.   
  32.         /// <summary>    
  33.         /// 把字节数组反序列化成对象    
  34.         /// </summary>    
  35.         public static object DeserializeObject(byte[] bytes)  
  36.         {  
  37.             object obj = null;  
  38.             if (bytes == null)  
  39.                 return obj;  
  40.             //利用传来的byte[]创建一个内存流  
  41.             MemoryStream ms = new MemoryStream(bytes);  
  42.             ms.Position = 0;  
  43.             BinaryFormatter formatter = new BinaryFormatter();  
  44.             obj = formatter.Deserialize(ms);//把内存流反序列成对象    
  45.             ms.Close();  
  46.             return obj;  
  47.         }  
  48.         /// <summary>  
  49.         /// 把字典序列化  
  50.         /// </summary>  
  51.         /// <param name="dic"></param>  
  52.         /// <returns></returns>  
  53.         public static byte[] SerializeDic(Dictionary<stringobject> dic)  
  54.         {  
  55.             if (dic.Count == 0)  
  56.                 return null;  
  57.             MemoryStream ms = new MemoryStream();  
  58.             BinaryFormatter formatter = new BinaryFormatter();  
  59.             formatter.Serialize(ms, dic);//把字典序列化成流  
  60.   
  61.             byte[] bytes = new byte[ms.Length];//从流中读出byte[]  
  62.             ms.Read(bytes, 0, bytes.Length);  
  63.   
  64.             return bytes;  
  65.         }  
  66.         /// <summary>  
  67.         /// 反序列化返回字典  
  68.         /// </summary>  
  69.         /// <param name="bytes"></param>  
  70.         /// <returns></returns>  
  71.         public static Dictionary<stringobject> DeserializeDic(byte[] bytes)  
  72.         {  
  73.             Dictionary<stringobject> dic = null;  
  74.             if (bytes == null)  
  75.                 return dic;  
  76.             //利用传来的byte[]创建一个内存流  
  77.             MemoryStream ms = new MemoryStream(bytes);  
  78.             ms.Position = 0;  
  79.             BinaryFormatter formatter = new BinaryFormatter();  
  80.             //把流中转换为Dictionary  
  81.             dic = (Dictionary<stringobject>)formatter.Deserialize(ms);  
  82.             return dic;  
  83.         }  
  84.     }  
  85.   
  86. }  

通用的数据包事件类

[csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Net;  
  5. using System.Text;  
  6. using System.Threading;  
  7. using Model;  
  8.   
  9. namespace ZZUdp.Core  
  10. {  
  11.     /// <summary>  
  12.     /// 数据包事件数据  
  13.     /// </summary>  
  14.     public class PackageEventArgs : EventArgs  
  15.     {  
  16.         /// <summary>  
  17.         /// 网络消息包  
  18.         /// </summary>  
  19.         public UdpPacket udpPackage { getset; }  
  20.   
  21.         /// <summary>  
  22.         /// 网络消息包组  
  23.         /// </summary>  
  24.         public UdpPacket[] udpPackages { getset; }  
  25.   
  26.         /// <summary>  
  27.         /// 远程IP  
  28.         /// </summary>  
  29.         public IPEndPoint RemoteIP { getset; }  
  30.   
  31.         /// <summary>  
  32.         /// 是否已经处理  
  33.         /// </summary>  
  34.         public bool IsHandled { getset; }  
  35.   
  36.         /// <summary>  
  37.         /// 创建一个新的 PackageEventArgs 对象.  
  38.         /// </summary>  
  39.         public PackageEventArgs(UdpPacket package, IPEndPoint RemoteIP)  
  40.         {  
  41.             this.udpPackage = package;  
  42.             this.RemoteIP = RemoteIP;  
  43.             this.IsHandled = false;  
  44.         }  
  45.     }  
  46. }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值