读书人

请问UDP分块发送图片有关问题(Delphi

发布时间: 2012-03-11 18:15:38 作者: rapoo

请教UDP分块发送图片问题—elphi XE+Indy 10)
Delphi XE的IDE有个Bug,因此IdUDPServer控件及OnUDPRead事件只好在运行时生成。请不要见怪。

我是想通过UDP将Img1中修改的部分发送到服务端,并重画在Img2上。现在能做的是,可以获得需要发送的最小矩形,使用SendBuffer命令以TMemoryStream方式将其划分成最大1024个字节大小进行发送。

客户端以'_STARTIMG_'为表示开始,‘_END__IMG_'表示发送结束;

服务端接收到“_STARTIMG_”之后开始接收数据,每次直接通过MemRec.Write(Adata, size)写入全局变量MemRec(TMemoryStream)。

当服务端收到‘_END__IMG_'之后结束结果,将MemRec内容画到IMG2上。

现在,的问题是MemRec无法画到IMG2上,而MemOld则可以。但通过CompareMem命令发现,两者的内容是相同的。这一点实在就想不通了。

由于这是一个还没理清头绪的程序,我的表述可能很不清楚。如有需要,请跟贴,我再做详细说明。

Delphi(Pascal) code
//发送程序procedure TForm1.btn1Click(Sender: TObject);var  mem: TMemoryStream;  Buf: array [0..1023] of Char;  pos, len: Integer;  RecStr: String;  TmpImg1, TmpImg2: TImage;  BitBuf: TBytes;begin  RectNew.Top:=0; RectNew.Left:=0;  RectNew.Bottom:=rect.Bottom-rect.Top;  RectNew.Right:=rect.Right-rect.Left;  form1.Caption:='';  mem:= TMemoryStream.Create;  TmpImg1:=TImage.Create(self);  TmpImg1.Picture.Bitmap.Width:=RectNew.Right;  TmpImg1.Picture.Bitmap.Height:=RectNew.Bottom;  TmpImg1.Canvas.CopyRect(RectNew, img1.Canvas, rect);  TmpImg1.Picture.Bitmap.SaveToStream(mem);              MemOld.Free;  MemOld:=TMemoryStream.Create;  TmpImg2:=TImage.Create(self);  TmpImg1.Picture.Bitmap.SaveToStream(MemOld);            //mem 和 MemOld的内容均正确//  MemOld.Position:=0;                                   //通过下面三句可以把画正确地画到IMG2中//  TmpImg2.Picture.Bitmap.LoadFromStream(MemOld);        //为了与传输结果比较,此处的MemOld为一全局变量//  img2.Canvas.CopyRect(rect, TmpImg2.Canvas,  rectnew);  if mem.Size>0 then begin    idpclnt1.Send('_STARTIMG_');    pos:=0;    while pos<mem.Size do begin      len:=1024;      if mem.Size-pos<1024 then len:=mem.Size-pos;      mem.Read(buf, len);      SetLength(BitBuf, len);      Move(buf[1], BitBuf[0], Len);      idpclnt1.SendBuffer(BitBuf);      inc(pos, len);    end;    idpclnt1.Send('_END__IMG_');  end;  Form1.Caption:=Form1.Caption+' end';  mem.Free;  TmpImg1.Free;  TmpImg2.Free;end;//接收程序procedure Tform1.UDPRead(AThread: TIdUDPListenerThread; AData: TArray<Byte>; ABinding: TIdSocketHandle);var  str, str1, str2: string;  size, i, flag: Integer;  tmp: TImage;  NewRect: TRect;  just: Boolean;begin  NewRect.Top:=0;  NewRect.Left:=0;  NewRect.Bottom:=rect.Bottom-rect.Top;  NewRect.Right:=rect.Right-rect.Left;  Flag:=1;  Size:=Length(AData);  if size=10 then begin    SetLength(str, 10);    for i := 1 to 10 do str[i]:=Char(AData[i-1]);    if str='_STARTIMG_' then begin      flag:=0;      form1.Tag:=1;    end;    if str='_END__IMG_' then begin      flag:=2;      form1.Tag:=0;    end;  end;  case flag of    0: begin        form1.Caption:=Form1.Caption+'S_';        MemRec:=TMemoryStream.Create;        form1.Caption:=Form1.Caption+'S_';      end;    2: begin        form1.Caption:=Form1.Caption+'_E';        tmp:=TImage.Create(self);        try            MemRec.Position:=0;            Form1.mmo1.Lines.Add(IntToStr(MemRec.Size)+ '  '+inttostr(MemOld.Size)) ;            MemOld.Position:=0;             //用MemOld可以正确地将需要的部分画到IMG2中            tmp.Picture.Bitmap.LoadFromStream(MemOld);            img2.Canvas.CopyRect(rect, tmp.Canvas, NewRect);//            MemRec.Position:=0;       //用MemRec 不能 需要的部分画到IMG2中//            tmp.Picture.Bitmap.LoadFromStream(MemRec);//            img2.Canvas.CopyRect(rect, tmp.Canvas, NewRect);            just:=CompareMem(MemRec.Memory,MemOld.Memory, MemOld.Size);                                       //但内存比较的结果是MemOld与MemRec的内容完全相同            if just then form1.mmo1.Lines.Add(IntToStr(1))            else form1.mmo1.Lines.Add(IntToStr(0));        finally          tmp.Free;          MemRec.Free;        end;        form1.img2.Canvas.MoveTo(0, 0);        form1.img2.Canvas.LineTo(30, 30);      end;    1: if form1.tag=1 then begin          MemRec.Write(Adata, size);          form1.Caption:=Form1.Caption+' - '+inttostr(MemRec.Size);      end;  end;end; 





[解决办法]

[解决办法]
UDP多包发送数据是需要进行丢包,包序检测的,随便出点网络堵塞你就会发现显示内容乱七八糟

读书人网 >.NET

热点推荐