博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C#中upd分包与发送,已经实现全部代码
阅读量:4518 次
发布时间:2019-06-08

本文共 16981 字,大约阅读时间需要 56 分钟。

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace Tool{        ///         /// UDP数据包分割器        ///         public static class UdpPacketSplitter        {            ///             /// 分割UDP数据包            ///             /// UDP数据包所持有的序号            /// 被分割的UDP数据包            /// 分割块的长度            /// 
/// 分割后的UDP数据包列表 ///
public static ICollection
Split(long sequence, byte[] datagram, int chunkLength) { if (datagram == null) throw new ArgumentNullException("datagram"); List
packets = new List
(); int chunks = datagram.Length / chunkLength; int remainder = datagram.Length % chunkLength; int total = chunks; if (remainder > 0) total++; for (int i = 1; i <= chunks; i++) { byte[] chunk = new byte[chunkLength]; Buffer.BlockCopy(datagram, (i - 1) * chunkLength, chunk, 0, chunkLength); packets.Add(new UdpPacket(sequence, total, i, chunk, chunkLength, remainder)); } if (remainder > 0) { int length = datagram.Length - (chunkLength * chunks); byte[] chunk = new byte[length]; Buffer.BlockCopy(datagram, chunkLength * chunks, chunk, 0, length); packets.Add(new UdpPacket(sequence, total, total, chunk, chunkLength, remainder)); } return packets; } }}

这是分包的算法

 

这是另外一个类

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace Tool{    [Serializable]    public class UdpPacket    {        public long sequence{get;set;}        public int total { get; set; }        public int i { get; set; }        public byte[] chunk { get; set; }        public int chunkLength { get; set; }        public int remainder { get; set; }        public static int HeaderSize = 30000;        public UdpPacket(long sequence, int total, int i, byte[] chunk, int chunkLength, int remainder)        {            this.sequence = sequence;            this.total = total;            this.i = i;            this.chunk = chunk;            this.chunkLength = chunkLength;            this.remainder = remainder;        }        //把这个对象生成byte[]        public byte[] ToArray()        {            return Model.SerializationUnit.SerializeObject(this);        }    }}

 然后对分包进行发送就行了的

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net.Sockets;using System.Collections;using System.Net;using Model;using System.Data;using Tool;namespace C_UDPServer{    public class Server    {        public UdpClient server;        public ArrayList mblist;        IPEndPoint test = null;//构造远程连接的参数        //保存用户的        public Dictionary
dic = new Dictionary
(); public bool flag=true; public Server(int port) { IPAddress myIPAddress = null; //获得当前的ip try { IPAddress[] address = Dns.GetHostAddresses(Dns.GetHostName()); foreach(IPAddress i in address) { if (i.AddressFamily.ToString().Equals("InterNetwork")) { myIPAddress = i; break; } } } catch (Exception e) { } //System.Console.Write(myIPAddress); string hostIP = myIPAddress.ToString(); IPAddress ipS = IPAddress.Parse(hostIP);//初始化本机 IPEndPoint EndPoint = new IPEndPoint(ipS, port); server = new UdpClient(EndPoint);//创建本地连接 //设置缓冲大小 server.Client.ReceiveBufferSize = 1024 * 1024; ShowServerinfo(hostIP + "启动成功!"); } //服务器接收数据的方法,会根据接收到的数据做出判断 public void ReceiveData() { ShowServerinfo("等待用户"); //未接收完的包 Dictionary
RecListDic = new Dictionary
(); while (flag) { try { //异步接收的....现在还不会 //AsyncCallback callBack = new AsyncCallback(ReceiveComplete); //server.BeginReceive(callBack, server); byte[] data = server.Receive(ref test);//接收数据,当Client端连接主机的时候,test就变成Cilent端的IP了 Msg msg = null; UdpPacket udpp = null; try { msg = (Msg)Model.SerializationUnit.DeserializeObject(data); } catch (Exception e1) { try { udpp = (UdpPacket)Model.SerializationUnit.DeserializeObject(data); } catch(Exception e2) { ShowServerinfo("解析序列话数据错误"); } //break; }; if (udpp != null) { ShowServerinfo("收到分包数据:" + udpp.i); if (!RecListDic.ContainsKey(udpp.sequence)) { RecListDic.Add(udpp.sequence, new RecDataList(udpp)); RecDataList rdl = RecListDic[udpp.sequence]; rdl.addPacket(udpp); } else{ RecDataList rdl=RecListDic[udpp.sequence]; rdl.addPacket(udpp); } foreach (KeyValuePair
ss in RecListDic)//循环看看是否有哪一个满了 { Msg m = ss.Value.show(); if (m != null) { ShowServerinfo(m.msg); RecListDic.Remove(ss.Value.sequence); break; } } } if (msg != null) { if (msg.command.Equals("ADD")) { string name = msg.name;//获得对象的名字 AddMember(name, test); } else if (msg.command.Equals("DEL")) { DelMember(test); } else if (msg.destinationIP != "") { //获得的ip包含了端口号的 string[] s = msg.destinationIP.Split(':'); string ip = s[0]; int port = int.Parse(s[1]); IPAddress ipS = IPAddress.Parse(ip); IPEndPoint destinationIP = new IPEndPoint(ipS, port); //单独把某个用户发送消息 SendToSB(test, destinationIP, msg.msg); //ShowServerinfo("ip:"+msg.destinationIP); } else { //判断是否这个人是在人员列表中存在 if (dic.ContainsValue(test)) { SendToMember(test, msg.msg);//转发数据 } } } } catch (Exception e) { ShowServerinfo("出异常了"); } } } //异步接收 private void ReceiveComplete(IAsyncResult param) { //UdpClient client=(UdpClient)param.AsyncState;//对应的就是BeginSend的最后一个参数state //IPEndPoint ipep = new IPEndPoint(IPAdress.Any,m_Port); //byte[] datas=client.EndReceive(param,ref ipep);//接受到的数据 //catch(Exception ex) {} } public void AddMember(string nickNmae, IPEndPoint rep)//加入组 { if (dic.ContainsValue(rep))//如果已经有这用户就返回 { return; } //存有用户信息的字典添加一个用户 dic.Add(nickNmae, rep); MsgService msg = new MsgService("success", "已连接", nickNmae, ""); sendEntitydata(msg,rep); //Console.WriteLine(nickNmae + "[" + rep.ToString() + "]" + "加入了组"); ShowServerinfo(nickNmae + "[" + rep.ToString() + "]" + "加入了组"); SendUserList(); //当用户更新后发送用户列表给所有用户 } public void DelMember(IPEndPoint rep)//移除组 { foreach (KeyValuePair
user in dic) { if (user.Value.Equals(rep)) { MsgService msg = new MsgService("exit", "退出了", "", ""); sendEntitydata(msg, rep); //Console.WriteLine(user.Key + "[" + rep.ToString() + "]" + "退出了组"); ShowServerinfo(user.Key + "[" + rep.ToString() + "]" + "退出了组"); dic.Remove(user.Key); SendUserList(); break;//否则会报错,因为dic已经被修改 } } } public void sendEntitydata(MsgService msg,IPEndPoint rep) { byte[] bytes = Model.SerializationUnit.SerializeObject(msg); //string data = Model.UDPComm.DecodingASCII(bytes); //byte[] bytedata = UDPComm.EncodingASCII(data);//发送数据 //server.Send(bytedata, bytedata.Length, rep); server.Send(bytes, bytes.Length, rep); } //发送用户表 public void SendUserList() { string userlist = "UserList"; foreach (KeyValuePair
ss in dic)//取得所有用户 { //userlist += "|" + ss.Key; userlist += "|" + ss.Key + "," + ss.Value.ToString(); } //序列化数据 MsgService msg = new MsgService("userList", "", "", ""); msg.userlist = userlist;//添加用户表 foreach (KeyValuePair
ss in dic)//把用户表发给每个用户 { sendEntitydata(msg, ss.Value); } } //单独发给某人 public void SendToSB(IPEndPoint user, IPEndPoint destinationIP, string message) { string name = ""; string destinationname = "";//收信息的人的名字 foreach (KeyValuePair
ss in dic)//用来找出这个user的名字 { if (ss.Value.Equals(user))//不能用"=="因为是两个不同的对象 { name = ss.Key;//得到发信息的人的名字 } if (ss.Value.Equals(destinationIP)) { destinationname = ss.Key;//得到收信人的名字 } } if (name != "" && destinationname != "") { //在服务端显示信息 ShowServerinfo(name + "[" + user.ToString() + "]:对" + destinationname + "[" + destinationIP.ToString() + "]说:" + message); //序列化数据 MsgService msg = new MsgService("talkone", message, name, destinationname); sendEntitydata(msg,destinationIP); sendEntitydata(msg, user); } } public void SendToMember(IPEndPoint user, string message)//组类转发数据(第一个参数是谁发的,第二个是发的内容) { string name = ""; foreach (KeyValuePair
ss in dic)//用来找出这个user的名字 { if (ss.Value.Equals(user))//不能用"=="因为是两个不同的对象 { name = ss.Key;//给要发送给各个客户端的信息加上发送人姓名; //在服务端显示的信息 //Console.WriteLine(name + "[" + user.ToString() + "]:" + message); ShowServerinfo(name + "[" + user.ToString() + "]:" + message); break; } } foreach (KeyValuePair
d in dic)//循环给每个人都发送信息 { //序列化数据 MsgService msg = new MsgService("talkall", message, name, ""); try { sendEntitydata(msg,d.Value); } catch (Exception e) { ShowServerinfo("给" + name+"发送信息失败!"); DelMember(d.Value); } } } //返回信息 public void ShowServerinfo(string servermsg) { System.Console.WriteLine(servermsg); } }}
using System;using System.Collections.Generic;using System.Linq;using System.Text;using Tool;using Model;namespace C_UDPServer{    //服务端收到数据的数据结构    public class RecDataList    {        public long sequence { get; set; }//序列号        //对应的存储包的List        List
RecudpPackets = new List
(); public int total { get; set; } public int chunkLength { get; set; } public int remainder { get; set; } public byte[] DataBuffer = null; public RecDataList(UdpPacket udp) { this.sequence = udp.sequence; this.total = udp.total; this.chunkLength = udp.chunkLength; this.remainder = udp.remainder; if (DataBuffer == null) { DataBuffer = new byte[chunkLength * (total - 1) + remainder]; } } public RecDataList(long sequence, int total, int chunkLength, int remainder) { this.sequence = sequence; this.total = total; this.chunkLength = chunkLength; this.remainder = remainder; if (DataBuffer == null) { DataBuffer = new byte[this.chunkLength * (this.total - 1) + this.remainder]; } } public void addPacket(UdpPacket p) { RecudpPackets.Add(p); } public Msg show() { if (RecudpPackets.Count == total)//表示已经收集满了 { //重组数据 foreach (UdpPacket udpPacket in RecudpPackets) { //偏移量 int offset = (udpPacket.i - 1) * udpPacket.chunkLength; Buffer.BlockCopy(udpPacket.chunk, 0, DataBuffer, offset, udpPacket.chunk.Length); } Msg rmsg = (Msg)Model.SerializationUnit.DeserializeObject(DataBuffer); DataBuffer = null; RecudpPackets.Clear(); return rmsg; } else { return null; } } }}

 

客户端代码 分包发送UDP数据

 

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using Model; using System.Net.Sockets; using C_UDPClient; using Tool; using System.Threading;

namespace UDPClient {     public class Client     {         public UdpClient client;         public bool flag = true;         public String nickname;         IPEndPoint remotIpEnd = null;//用来在接收数据的时候对远程主机的信息存放         public int port;         public string hostIP;         public Client(string hostIP, int port, string nick)         {             IPAddress ipA = IPAddress.Parse(hostIP);//构造远程连接的参数             IPEndPoint ipEnd = new IPEndPoint(ipA, port);             client = new UdpClient();// client = new UdpClient(ipEnd)这样的话就没有创建远程连接             client.Connect(ipEnd);//使用指定的远程主机信息建立默认远程主机连接             this.nickname = nick;             this.port = port;             this.hostIP = hostIP;         }         public void SendData(string message)         {             try             {                 byte[] data = UDPComm.EncodingASCII(message);//发送数据                 client.Send(data, data.Length);             }             catch (Exception e)             {                 AddTalkMessage("发送数据异常1!");                 //client.Close();             }         }         //发送大数据的方法         public void SendManyPacket(Msg message)         {             byte[] datagram = null;             try             {                 datagram = Model.SerializationUnit.SerializeObject(message);             }             catch (Exception e)             {                 AddTalkMessage("数据转型异常");             }                         Random Rd = new Random();             long SequenceNumber = Rd.Next(88888, 999999);             ICollection<UdpPacket> udpPackets = UdpPacketSplitter.Split(SequenceNumber, datagram, 10240);//65507 - UdpPacket.HeaderSize             foreach (UdpPacket udpPacket in udpPackets)             {                 byte[] udpPacketDatagram = Model.SerializationUnit.SerializeObject(udpPacket);                 //使用同步发送                 //Thread.Sleep(1000); //如果加了这条就不丢包                 //client.Send(udpPacketDatagram, udpPacketDatagram.Length);                 // 异步发送                 //Thread.Sleep(1000); //如果加了这条就不丢包                 this.client.BeginSend(                 udpPacketDatagram,                 udpPacketDatagram.Length, SendCompleted, new AsyncCallbackArg(udpPacket.i.ToString(), client));             }         }         //发送完成后的回调方法         public void SendCompleted(IAsyncResult param)         {             /*             //AsyncCallbackArg arg = (AsyncCallbackArg)param.AsyncState ;//param.AsyncState 对应的就是BeginSend的最后一个参数state                  UdpClient client = (UdpClient)param.AsyncState;             try               {                   client.EndSend(param);//这句话必须得写,BeginSend()和EndSend()是成对出现的                   AddTalkMessage("数据包发送完毕!");               }               catch (Exception e) { }              */          }

        public void SendData(Msg message)         {             try             {                 byte[] bytes = Model.SerializationUnit.SerializeObject(message);                 client.Send(bytes, bytes.Length);             }             catch (Exception e)             {                 AddTalkMessage("发送数据异常2!");             }         }         public void ReceiveData()         {             while (flag)             {                 try                 {                     byte[] data = client.Receive(ref remotIpEnd);//接收数据,当Client端连接主机的时候,test就变成Cilent端的IP了                     MsgService msg = null;                     try                     {                         msg = (MsgService)Model.SerializationUnit.DeserializeObject(data);                     }                     catch (Exception e)                     {                         AddTalkMessage("解析序列话数据错误..");                     };                     if (msg.command.Equals("userList"))                     {                         AddUserList(msg.userlist);                         //AddTalkMessage(ReturnData);                         continue;                     }                     if (msg.name.Equals(nickname))                     {                         AddTalkMessage(msg);                     }                     else                     {                         AddTalkMessage(msg);

                    }                 }                 catch (Exception e)                 {                     AddTalkMessage("未连接..");                     break;                 }             }         }         public void AddUserList(string s)         {             System.Console.WriteLine("用户表为:" + s);         }         public void AddTalkMessage(string s)         {             System.Console.WriteLine(s);         }         public void AddTalkMessage(MsgService s)         {             System.Console.WriteLine(s.ToString());         }

 

        //异步发送数据的数据结构         private struct AsyncCallbackArg         {             private UdpClient udpClient;             private string ipAddress;             public AsyncCallbackArg(string ip, UdpClient client)             {                 udpClient = client;                 ipAddress = ip;             }         }     } }

 

 

转载于:https://www.cnblogs.com/zhujunxxxxx/p/3344872.html

你可能感兴趣的文章
多个视图控制器的返回
查看>>
Codeforces Round #451 Div. 2 C D E
查看>>
快速构建编辑类型弹出窗口
查看>>
室外光缆结构
查看>>
【JZOJ3400】旅行
查看>>
第5.2次作业
查看>>
luoguP5108 仰望半月的夜空 [官方?]题解 后缀数组 / 后缀树 / 后缀自动机 + 线段树 / st表 + 二分...
查看>>
Mysql学习第一天
查看>>
031 oracle环境下的Start with...Connect By递归树查询
查看>>
深入浅出 Java Concurrency (17): 并发容器 part 2 ConcurrentMap (2)[转]
查看>>
【 HYSBZ - 2440 】完全平方数 (莫比乌斯函数容斥)
查看>>
最优矩阵链乘
查看>>
2012年软件大赛校内选拔赛
查看>>
2017 Java面试大全(一)
查看>>
PHP实现四种基本排序算法
查看>>
Poj3414广搜
查看>>
云南南天电子信息产业股份有限公司某站SQL注入漏洞
查看>>
09-C#笔记-循环
查看>>
3.20下午
查看>>
AngularJS之代码风格36条建议【一】(九)
查看>>