可恶的TIdUDPClient!(50分)

  • 主题发起人 主题发起人 dqxhyy
  • 开始时间 开始时间
D

dqxhyy

Unregistered / Unconfirmed
GUEST, unregistred user!
我写这个代码
var
m:tmemorystream;
....
....
idudpc.sendbuffer(ip,port,m,m.size);
....
当m.size大小小于一定数值的时候,没问题,当大于一个数值的时候,就会出现#10014错误,说是bad address.
请问怎么解决呢
 
好象包的大小是不能超过1500B的啊,你只能拆包发送,收到后再重新组包。

不过我测试过,如果用Send(String)的时候,好象就没这个限制。
 
通过UDP发包肯定是有大小限制的,你想一个文件有5M,一次性发送,什么网络能受得了呀?以前做过一个UDP发送软件,供你参考一下:


unit udpservers;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
IdBaseComponent, IdComponent, IdUDPBase, IdUDPClient, ExtCtrls,jpeg,forms;

type
Tsnapscreen = class(TService)
Timer1: TTimer;
IdUDPClient1: TIdUDPClient;
procedure ServiceCreate(Sender: TObject);
procedure ServiceDestroy(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
function GetServiceController: TServiceController; override;
{ Public declarations }
end;

var
snapscreen: Tsnapscreen;
FStream : TMemoryStream;

implementation

const
bufsize=4096-1;


{$R *.DFM}

procedure ServiceController(CtrlCode: DWord); stdcall;
begin
snapscreen.Controller(CtrlCode);
end;

function Tsnapscreen.GetServiceController: TServiceController;
begin
Result := ServiceController;
end;

procedure Tsnapscreen.ServiceCreate(Sender: TObject);
begin
Timer1.Interval:=60000;
IdUdpClient1.Host:='172.16.88.3';
IdUdpClient1.Port:=9090;
timer1.Enabled:=true;
FStream:=TMemoryStream.Create;
end;

procedure Tsnapscreen.ServiceDestroy(Sender: TObject);
begin
FStream.Free;
end;

procedure Tsnapscreen.Timer1Timer(Sender: TObject);
var
receivedstring,filename,dirname:string;
dc:hdc;
fjpeg:tjpegimage;
fscreencanvas:tcanvas;
fbitmap:Tbitmap;
buf:array[0..bufsize] of char;
sendlen:integer;
intoffset:int64;
sRect,Drect:TRect;
name:pchar;
len:dword;
begin
fbitmap:=nil;
fjpeg:=nil;
fscreencanvas:=nil;
dc:=0;
try
filename:=formatdatetime('yyyymmddhhnnsszzz',now);
idudpclient1.Send('send'+filename);
application.ProcessMessages;
receivedstring:=idudpclient1.ReceiveString();
if uppercase(receivedstring)='OK' then
begin
dc:=getdc(0);
fScreencanvas:=Tcanvas.Create;
Fscreencanvas.Handle:=dc;
fbitmap:=tbitmap.Create;
fbitmap.Width:=screen.Width;
fbitmap.Height:=screen.Height;
sRect:=Rect(0,0,screen.Width,screen.Height);
dRect:=Rect(0,0,screen.Width,screen.Height);
fbitmap.Canvas.CopyRect(sRect,fscreencanvas,dRect);
fbitmap.Canvas.Brush.Style:=bsClear;
fbitmap.Canvas.Font.Color:=clRed;
fbitmap.Canvas.Font.Size:=30;
getmem(name,30);
len:=30;
getcomputername(name,len);
fbitmap.Canvas.TextOut(10,30,name+' '+formatdatetime('yyyy-mm-dd hh:nn',now));
freemem(name);
fjpeg:=Tjpegimage.Create;
fjpeg.Assign(fbitmap);
fscreencanvas.Free;
fbitmap.Free;
releasedc(0,dc);
fjpeg.CompressionQuality:=8;
fjpeg.SaveToStream(fstream);
fstream.Position:=0;
fjpeg.Free;
intoffset:=0;
while true do
begin
if intoffset>=fstream.Size then break;
fstream.Position:=intoffset;
sendlen:=fstream.Read(buf,sizeof(buf));
idudpclient1.SendBuffer(buf,sendlen);
application.ProcessMessages;
intoffset:=intoffset+sendlen;
end;
fstream.Clear;
idudpclient1.Send('end');
end;
except


;
end;
end;

end.
 
将UDP包大小设计在MTU范围以内,一般1400左右试试。特别是网络阻塞的情况下,
UDP包大小很关键,接收当中也有可能前后颠到,顺序不一致要重新组包。
因为UDP是无连接的,包每次传输的路线可能不尽相同.
 
var
m:tmemorystream;
....
....
idudpc.sendbuffer(ip,port,m.memory^,m.size);//**********用这个试一下
....
 
一次性发关越大,成功的机率就越小,因为它要被分成很多小包,必须每个小包都正确才能成功.
 
多人接受答案了。
 
后退
顶部