当前位置:编程学习 > C#/ASP.NET >>

UDP 分包发送然后接收组装代码、出点小问题、大虾帮忙找下。

麻烦大家抽点时间看看下边代码、发送和接收都很正常、但是组装的时候可能出错了、格式化成图片的时候出现了参数错误、
发送的图片流跟接收的图片流一致!有兴趣的朋友可以调试一下、一下是我写的公共代码、谢谢大家!

        public bool IsStartSendScreen= false;
        public static string ErrorMsg = string.Empty;
 public void SendScreenByUdp(IPEndPoint TargetIep, int LocalPort, string SendType, int PacketSize,int time)
        {
            UdpClient uc = new UdpClient(LocalPort);
            UitlClass uitl = new UitlClass();
            MemoryStream Ms = new MemoryStream();
            long MsLength = 0;
            int DataID = 1;//包编号
            int CurIndex = 0;//当前包在图片流中的下标
            long Page = 1;//已发送图片张数
            int LastPageSize=0;//最后一个包大小
            byte[] datas = new byte[PacketSize];//声明字节数组
            int CurPackSize = 0;//当前包大小
            int MsImgLength = 0;
            if (SendType.Equals("Multicast"))
            {
                uc.JoinMulticastGroup(TargetIep.Address);
                uc.EnableBroadcast = true;
            }
            while (IsStartSendScreen)
            {
                Bitmap bit = uitl.GetDisk();//获取桌面位图
                bit.Save(Ms, ImageFormat.Jpeg);//保存到内存流
                bit.Dispose();//释放
                MsLength = Ms.Length;
                //计算出总共需要分多少包才可以发送完一幅图片
                int MaxPacketCount =(int) Math.Ceiling(double.Parse(MsLength.ToString()) / double.Parse((PacketSize-28).ToString()));
                LastPageSize = (int)MsLength % (PacketSize - 28) + 28;//得到最后一个包的长度
                for (int i = 0; i < MaxPacketCount; i++)
                {
                    if (DataID == MaxPacketCount)
                    {
                        CurPackSize = LastPageSize;
                    }
                    else
                    {
                        CurPackSize = PacketSize;
                    }
                    BitConverter.GetBytes(DataID).CopyTo(datas, 0);//包编号0-4位
                    BitConverter.GetBytes(MsLength).CopyTo(datas, 4);//流长度4-8位
                    BitConverter.GetBytes(Page).CopyTo(datas, 12);//此包体属于哪一幅图片
                    BitConverter.GetBytes(CurIndex).CopyTo(datas, 20);//当前包在图片流中的开始坐标
                    BitConverter.GetBytes(CurPackSize).CopyTo(datas, 24);//当前包大小
                    if (MaxPacketCount == DataID)
                    {
                        Ms.Read(datas, 28, LastPageSize - 28);
                        CurIndex += LastPageSize;
                    }
                    else
                    {
                        Ms.Read(datas, 28, PacketSize - 28);
                        CurIndex += PacketSize;
                    }
                    MsImgLength += CurPackSize - 28;
                    MessageBox.Show("数据包长度" + datas.Length + "图片流总长度" + Ms.Length + "已发送图片流长度" + MsImgLength);
                    uc.Send(datas, datas.Length, TargetIep);//发送
                    
                    DataID++;//包编号
                    Ms.Seek(MsImgLength, SeekOrigin.Begin);//设定下一个包的读取位置为流的起始位置
                } 
              //  MessageBox.Show(MsImgLength.ToString());
                Ms.Seek(0, SeekOrigin.Begin);//已经发送完毕一幅图片、将流的起始位置设置为0
                CurIndex = 0;
                DataID = 1;
                Page++;//发送完毕一幅图片要将已发张数++
                MsImgLength = 0;
                Thread.Sleep(time);
            }
            Ms.Close();
            uc.Close();
        }



        public bool IsStartRecScreen= false;
        public static string ErrorMsg = string.Empty;
  public void RecScreenByUdp(IPEndPoint TargetIep, ref IPEndPoint RemoteIep, PictureBox Pic,string SendType)
        {
            UdpClient uc = new UdpClient(TargetIep.Port);
            if (SendType.Equals("Multicast"))
            {
                uc.EnableBroadcast = true;
                uc.MulticastLoopback = false;
                uc.JoinMulticastGroup(TargetIep.Address);
            }
            byte[] datas = null;
            MemoryStream Ms = null;
            int CurPage = 0;
            int DataID = 0;
            long MsLength = 0;
            long Page = 0;
            int CurIndex = 0;
            int CurPackSize = 0;
            int ImgMslength = 0;
            while (IsStartRecScreen)
            {
                Ms = new MemoryStream();
                datas = uc.Receive(ref RemoteIep);//接收数据
                DataID = BitConverter.ToInt32(datas, 0);//包编号
                MsLength = BitConverter.ToInt64(datas, 4);//一幅图片流的长度
                Page = BitConverter.ToInt64(datas, 12);//此包体属于哪一幅图片
                CurIndex = BitConverter.ToInt32(datas, 20);//当前包在流中的开始下标
                CurPackSize = BitConverter.ToInt32(datas, 24);//获得当前包大小
                ImgMslength += CurPackSize - 28;
                //Ms.SetLength(MsLength);
                MessageBox.Show("数据报ID" + DataID.ToString()+"图片流总长度"+MsLength+"已接收图片流长度:"+ImgMslength.ToString());
                // 如果开始接收下一幅图片
                if (Page != CurPage)
                {
                    Ms.Seek(0, SeekOrigin.Begin);
                    Ms.Write(datas, 28, datas.Length - 28);
                    Ms.Seek(ImgMslength, SeekOrigin.Begin);
                    CurPage++;
                }
                else
                {
                    if (ImgMslength == MsLength)
                    {
                        try
                        {
                            Pic.Image = Image.FromStream(Ms);
                            ImgMslength = 0;
                        }
                        catch (Exception exception)
                        {
                            ErrorMsg = "格式化图片出错:" + exception.Message;
                            return;
                        }
                    }
                    Ms.Write(datas, 28, datas.Length - 28);
                    Ms.Seek(ImgMslength, SeekOrigin.Begin);
                   // MessageBox.Show("已接收图片流长度" + ImgMslength.ToString());
                }
            }
            Ms.Close();
            uc.Close();
        }



--------------------编程问答-------------------- 为了方便调试、我把截屏的代码也一起发出来

[DllImportAttribute("user32.dll")]
        private static extern IntPtr GetDC(IntPtr WndHd);
        [DllImportAttribute("user32.dll")]
        private static extern IntPtr GetDesktopWindow();
        [DllImportAttribute("user32.dll")]
        private static extern void ReleaseDC(IntPtr ip);
        [DllImportAttribute("gdi32.dll")]
        private static extern IntPtr GetCurrentObject(IntPtr ip, ushort u);
        const int s = 7;


        public Bitmap GetDisk()
        {
            Bitmap b = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
            IntPtr W = GetDesktopWindow();
            IntPtr DC = GetDC(W);
            b = Image.FromHbitmap(GetCurrentObject(DC, s));
            ReleaseDC(DC);
            return b;
        }

--------------------编程问答-------------------- 帖子沉的真快、、、、我做不下去了 我从发送到接受一遍一遍的度、、一遍遍的过、我感觉是对的呀、、 --------------------编程问答-------------------- 顶上去!! --------------------编程问答-------------------- 没法、沉的太快  换个马甲接着顶!  希望高手出现 --------------------编程问答-------------------- 有时间的 请帮我看看代码吧。 --------------------编程问答-------------------- 疯了、没人理我? --------------------编程问答-------------------- 考虑UDP传输丢包问题了吗?还有Thread.sleep(time)这个时间设多少比较合适呢?问一下您的能实现了吗? --------------------编程问答-------------------- 如何根据包的编号进行丢包处理,丢包后是重传还是丢弃?
补充:.NET技术 ,  C#
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,