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();
}
--------------------编程问答-------------------- 帖子沉的真快、、、、我做不下去了 我从发送到接受一遍一遍的度、、一遍遍的过、我感觉是对的呀、、 --------------------编程问答-------------------- 顶上去!! --------------------编程问答-------------------- 没法、沉的太快 换个马甲接着顶! 希望高手出现 --------------------编程问答-------------------- 有时间的 请帮我看看代码吧。 --------------------编程问答-------------------- 疯了、没人理我? --------------------编程问答-------------------- 考虑UDP传输丢包问题了吗?还有Thread.sleep(time)这个时间设多少比较合适呢?问一下您的能实现了吗? --------------------编程问答-------------------- 如何根据包的编号进行丢包处理,丢包后是重传还是丢弃?
[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;
}
补充:.NET技术 , C#