zoukankan      html  css  js  c++  java
  • C#中upd分包与发送,已经实现全部代码

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Tool
    {
            /// <summary>
            /// UDP数据包分割器
            /// </summary>
            public static class UdpPacketSplitter
            {
                /// <summary>
                /// 分割UDP数据包
                /// </summary>
                /// <param name="sequence">UDP数据包所持有的序号</param>
                /// <param name="datagram">被分割的UDP数据包</param>
                /// <param name="chunkLength">分割块的长度</param>
                /// <returns>
                /// 分割后的UDP数据包列表
                /// </returns>
                public static ICollection<UdpPacket> Split(long sequence, byte[] datagram, int chunkLength)
                {
                    if (datagram == null)
                        throw new ArgumentNullException("datagram");
    
                    List<UdpPacket> packets = new List<UdpPacket>();
    
                    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<string, IPEndPoint> dic = new Dictionary<string, IPEndPoint>();
            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<long, RecDataList> RecListDic = new Dictionary<long, RecDataList>();
                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<long, RecDataList> 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<string, IPEndPoint> 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<string, IPEndPoint> ss in dic)//取得所有用户
                {
                    //userlist += "|" + ss.Key;
                    userlist += "|" + ss.Key + "," + ss.Value.ToString();
                }
    
                //序列化数据
                MsgService msg = new MsgService("userList", "", "", "");
                msg.userlist = userlist;//添加用户表
                foreach (KeyValuePair<string, IPEndPoint> ss in dic)//把用户表发给每个用户
                {
                    sendEntitydata(msg, ss.Value);
                }
    
            }
            //单独发给某人
            public void SendToSB(IPEndPoint user, IPEndPoint destinationIP, string message)
            {
                string name = "";
                string destinationname = "";//收信息的人的名字
                foreach (KeyValuePair<string, IPEndPoint> 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<string, IPEndPoint> 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<string, IPEndPoint> 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<UdpPacket> RecudpPackets = new List<UdpPacket>();
            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;             }         }     } }


     

  • 相关阅读:
    关于jar项目发布(windows)
    SpringBoot 基础(一) mybatis 通过druid配置多数据库
    redis 基础(二) Redis安装
    测试开发3年,我决定去读个名校硕士
    大厂程序员凡尔赛的一天
    假如我拥有字节工牌。。。
    上海有哪些牛逼的互联网公司?
    那些学计算机的女生后来都怎么样了?
    微信支付零花钱刷屏了!5万额度,能花又能借
    清华集训 part1
  • 原文地址:https://www.cnblogs.com/zhujunxxxxx/p/3344872.html
Copyright © 2011-2022 走看看