udp广播问题?(50分)

  • 主题发起人 主题发起人 crodling
  • 开始时间 开始时间
C

crodling

Unregistered / Unconfirmed
GUEST, unregistred user!
我使用udp广播抓取下来的当前屏幕图象,为什么我发送了十一次,客户端只收到六次呢?我尝试了好几次都是一样的结果,很是困惑
望能帮忙解决一下
 
有可能是丢包吧
建议还是不用广播
容易出现问题
我原来的一个程序用了广播
在20台机器好用没有任何问题
在70台机器就不行了,老是通讯不了
不知道是不是广播发的太多了
 
呵呵,不用广播我这个程序还怎么做下去啊~

 
丢包,不用广播,用多播吗,这样效率要好点
 
不过这样的丢包现象也太过严重了吧,而且还是在单机上面,要是放到局域网中,那还要丢多少呢?
 
你发送中间sleep()一会,而且每个包最好不要超过2K
 
能不能帮我看看哪里出问题了呢?
源码如下:
发送端sender.pas
……
var
SendSize:integer;
Buf:array[0..BufSize-1] of char;
i,j,iHead:Integer;
LocalIP,sHead,s:String;
ai:array [1..3] of integer;
ReqCode:array[0..29] of char;ReqCodeStr:string;
begin
Application.Minimize;
BmpStream:=TMemoryStream.Create;
BroadCastIP='127.255.255.255'
CUDP.RemoteHost:=BroadCastIP; { BroadCastIP为广播地址 }
if BmpStream.Size=0 then { 没有数据可发,必须截屏生成数据 }
ScreenCap(0,0,300,300); {截取屏幕 }
while LeftSize>BufSize do
begin
k:=k+1;
SendSize:=BufSize;
BmpStream.ReadBuffer(Buf,SendSize);
LeftSize:=LeftSize-SendSize;
if LeftSize=0 then
begin
BmpStream.Clear;{如果剩余数据为空,清空流 }
exit;
end;
CUDP.SendBuffer(Buf,SendSize); { 将数据发到主控机的2222口 }
end;
SendSize:=LeftSize;
BmpStream.ReadBuffer(Buf,SendSize);
LeftSize:=LeftSize-SendSize;
CUDP.SendBuffer(Buf,SendSize); { 将数据发到主控机的2222口 }
……
接收端:receiver.pas
……
procedure TForm1.SUDPDataReceived(Sender: TComponent;
NumberBytes: Integer; FromIP: String; Port: Integer);
begin
SUDP.ReadStream(TmpStream);
RsltStream.CopyFrom(TmpStream,NumberBytes);
if NumberBytes< BufSize then { 数据已读完 }
begin
RsltStream.Position:=0;
Image1.Picture.Bitmap.LoadFromStream(RsltStream);
label1.caption:='received';
TmpStream.Clear;
RsltStream.Clear;
end;

end;
 
神哪,上帝啊,天主啊,各位富翁啊,帮个忙吧,我调试了一下午,大脑都已经麻痹了,伸把援手如何?
 
这个代码是不是从别人那拷过来的呀,很多地方要修改的
 
我是拷过来的,不过现在已经大部分是我自己写的,怎么会很多地方要修改呢。
我只是有一些过程省略了没有写而已啊。
整个程序基本上可以运行了,发送端现在可以发送数据,客户端也可以接收,但是现在只是
不知道到底是发送端有问题,还是接收端出了问题,
接收端显示的图象,是由截取下来的屏幕图象的一小部分重叠显示,而不是本应该显示的截
取下来的图象。

可是我在这里加了附加条件的啊!

在发送端的程序,我要求的是“while LeftSize>BufSize do ”的时候发送端就一直发
送数据(发送的数据大小为BufSize),直到剩余的数据小于BufSize的时候,再最后发送一
次,才结束发送。

因此说当发送端发送过来的数据小于BufSize的时候,就是已经接受完发送端发送过来的数
据,程序才调用显示图象的功能(Image1.Picture.Bitmap.LoadFromStream(RsltStream) ),即开始执行以下的代码。
if NumberBytes< BufSize then { 数据已读完 }
begin
RsltStream.Position:=0;
Image1.Picture.Bitmap.LoadFromStream(RsltStream);
label1.caption:='received';
TmpStream.Clear;
RsltStream.Clear;
end;


可是这里有这样的一个问题存在,就是接收端显示的图象是截取下来的屏幕的一小部分的
重叠。所以很是让人困惑

 
你把图象保存到内存里,循环发送,一次最多2K,中间sleep(80~120)应该就没有问题
 
to 张无忌,:
恩,我设置的buffersize是2048刚好2k,而且中间也sleep了却还是不行,现在全部代码在下面
您如果有空的话就帮忙看看

发送端

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, NMUDP, StdCtrls, Psock;

type
TForm1 = class(TForm)
CUDP: TNMUDP;
Label1: TLabel;
Timer1: TTimer;
Label2: TLabel;
Powersock1: TPowersock;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure ScreenCap(LeftPos,TopPos,RightPos,BottomPos:integer);
private
{ Private declarations }

public
{ Public declarations }
end;

var
Form1: TForm1;
BmpStream:TMemoryStream;
BroadCastIP:string;
LeftSize:Longint;{ 发送每一笔数据后剩余的字节数 }
implementation

{$R *.DFM}
const BufSize=2048;{ 发送每一笔数据的缓冲区大小 }

procedure TForm1.FormCreate(Sender: TObject);

var
SendSize:integer;
Buf:array[0..BufSize-1] of char;
i,j,iHead:Integer;
LocalIP,sHead,s:String;
ai:array [1..3] of integer;
begin
Application.Minimize;
BmpStream:=TMemoryStream.Create;
LocalIP:=Powersock1.LocalIP;//本机ip
BroadCastIP:=LocalIP;
CUDP.RemoteHost:=BroadCastIP; { BroadCastIP为广播地址 }
if BmpStream.Size=0 then { 没有数据可发,必须截屏生成数据 }
ScreenCap(0,0,100,100); {截取屏幕 }
while LeftSize>BufSize do
begin
SendSize:=BufSize;
BmpStream.ReadBuffer(Buf,SendSize);
//把要发送的数据读入buf中
LeftSize:=LeftSize-SendSize;
//计算剩余的数据
if LeftSize=0 then
begin
BmpStream.Clear;{如果剩余数据为空,清空流 }
exit;
end;
CUDP.SendBuffer(Buf,SendSize); { 将数据发到主控机的2222口 }
sleep(100);
end;
SendSize:=LeftSize;
BmpStream.ReadBuffer(Buf,SendSize);
LeftSize:=LeftSize-SendSize;
CUDP.SendBuffer(Buf,SendSize); { 将数据发到主控机的2222口 }
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
BmpStream.Free;
end;

procedure TForm1.ScreenCap(LeftPos, TopPos, RightPos, BottomPos: integer);
var
RectWidth,RectHeight:integer;
SourceDC,DestDC,Bhandle:integer;
Bitmap:TBitmap;
begin
Application.Minimize;
RectWidth:=RightPos-LeftPos;
RectHeight:=BottomPos-TopPos;
SourceDC:=CreateDC('DISPLAY','','',nil);
DestDC:=CreateCompatibleDC(SourceDC);
Bhandle:=CreateCompatibleBitmap(SourceDC,RectWidth,RectHeight);
SelectObject(DestDC,Bhandle);
BitBlt(DestDC,0,0,RectWidth,RectHeight,SourceDC,LeftPos,TopPos,SRCCOPY);
Bitmap:=TBitmap.Create;
Bitmap.Handle:=BHandle;
BitMap.SaveToStream(BmpStream);
BmpStream.Position:=0;
LeftSize:=BmpStream.Size;
Bitmap.Free;
DeleteDC(DestDC);
ReleaseDC(Bhandle,SourceDC);
end;
end.

接收端

unit server;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
NMUDP, StdCtrls, ExtCtrls, Psock;

type
TForm1 = class(TForm)
SUDP: TNMUDP;
Image1: TImage;
Edit1: TEdit;
Edit2: TEdit;
Label1: TLabel;
Powersock1: TPowersock;
Label2: TLabel;
Button1: TButton;
Label3: TLabel;
procedure FormCreate(Sender: TObject);
procedure SUDPDataReceived(Sender: TComponent; NumberBytes: Integer;
FromIP: String; Port: Integer);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
RsltStream,TmpStream:TMemoryStream;
temp:integer;

implementation

{$R *.DFM}
const BufSize=2048;

procedure TForm1.FormCreate(Sender: TObject);
begin
RsltStream:=TMemoryStream.Create;
TmpStream:=TMemoryStream.Create;
MyStream1:=TMemoryStream.Create;
end;


procedure TForm1.SUDPDataReceived(Sender: TComponent;
NumberBytes: Integer; FromIP: String; Port: Integer);
begin
SUDP.ReadStream(TmpStream);
RsltStream.CopyFrom(TmpStream,NumberBytes);
if NumberBytes<BufSize then
begin
RsltStream.Position:=0;
Image1.Picture.Bitmap.LoadFromStream(RsltStream);
TmpStream.Clear;
RsltStream.Clear;
end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
RsltStream.Free;
TmpStream.Free;
end;


end.


 
你可以用delphi6中的IdUdpServer 啊,一次可以发送64k
 
丢保现象不是很严重
 
IdUdpServer一次发64K,你搞错没?
这样很容易分片,一般UDP一个包到了2K以上就很容易出问题
 
果然是udp丢包问题,我设置了sleep(1000)的时候才终于才成功发送出去。唉,
要是一秒才发送一副图片的话,这个速度也太慢了,
 
你每次发送的数据都小一点,你用抓包软件看看netmeeting每次发送的包大小就知道你
应该发送多大的数据包了...........
 
多人接受答案了。
 

Similar threads

D
回复
0
查看
911
DelphiTeacher的专栏
D
D
回复
0
查看
868
DelphiTeacher的专栏
D
D
回复
0
查看
840
DelphiTeacher的专栏
D
后退
顶部