Delphi 2010 下的 Indy UDP 读取发送范例。

首先新建服务端。

  如下图所示建立工程:

Delphi 2010 下的 Indy UDP 读取发送范例。

代码如下:

1 unitClientUnit;

2 interface

3 uses

4  Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,

5  Dialogs,StdCtrls,ExtCtrls,IdBaseComponent,IdComponent,IdUDPBase,

6  IdUDPClient,IdAntiFreezeBase,IdAntiFreeze;

7 type

8  TClientForm=class(TForm)

9   Label1:TLabel;

10   Edit1:TEdit;

11   Button1:TButton;

12   Label2:TLabel;

13   IdUDPClient1:TIdUDPClient;

14   IdAntiFreeze1:TIdAntiFreeze;

15   ListBox1:TListBox;

16   Timer1:TTimer;

17   procedureButton1Click(Sender:TObject);

18   procedureFormCreate(Sender:TObject);

19   procedureTimer1Timer(Sender:TObject);

20  private

21   {Privatedeclarations}

22   varIpList:TStringList;

23  public

24   {Publicdeclarations}

25  end;

26 var

27  ClientForm:TClientForm;

28 implementation

29 {$R*.dfm}

30 procedureTClientForm.Button1Click(Sender:TObject);

31 begin

32  IdUDPClient1.Broadcast(Edit1.Text,3030);

33  ListBox1.Items.Add(IdUDPClient1.ReceiveString());

34 end;

35 procedureTClientForm.FormCreate(Sender:TObject);

36 begin

37  IdUDPClient1.ReceiveTimeout:=10000;

38  IpList:=TStringList.Create;

39 end;

40 procedureTClientForm.Timer1Timer(Sender:TObject);

41 varipaddr:string;

42 varI:Integer;

43 begin

44  IdUDPClient1.BroadcastEnabled:=True;

45  IdUDPClient1.Broadcast('SearchHost',3030);

46  ipaddr:=IdUDPClient1.ReceiveString();

47  ifIpList.IndexOf(ipaddr)=-1then

48   IpList.Add(ipaddr);

49  ListBox1.Clear;

50  forI:=0toIpList.Count-1do

51   ListBox1.Items.Add(IpList.Strings[I]);

52 end;

53 end.

54

Delphi 2010 下的 Indy UDP 读取发送范例。

代码如下:

1 unitClientUnit;

2 interface

3 uses

4  Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,

5  Dialogs,StdCtrls,ExtCtrls,IdBaseComponent,IdComponent,IdUDPBase,

6  IdUDPClient,IdAntiFreezeBase,IdAntiFreeze;

7 type

8  TClientForm=class(TForm)

9   Label1:TLabel;

10   Edit1:TEdit;

11   Button1:TButton;

12   Label2:TLabel;

13   Edit2:TEdit;

14   IdUDPClient1:TIdUDPClient;

15   IdAntiFreeze1:TIdAntiFreeze;

16   procedureButton1Click(Sender:TObject);

17   procedureFormCreate(Sender:TObject);

18  private

19   {Privatedeclarations}

20  public

21   {Publicdeclarations}

22  end;

23 var

24  ClientForm:TClientForm;

25 implementation

26 {$R*.dfm}

27 procedureTClientForm.Button1Click(Sender:TObject);

28 begin

29  IdUDPClient1.Broadcast(Edit1.Text,3030);

30  Edit2.Text:=IdUDPClient1.ReceiveString(-1);

31 end;

32 procedureTClientForm.FormCreate(Sender:TObject);

33 begin

34  IdUDPClient1.ReceiveTimeout:=5000;

35  Edit2.ReadOnly:=True;

36 end;

37 end.

38

Delphi 2010 下的 Indy UDP 读取发送范例。

客户端:

Delphi 2010 下的 Indy UDP 读取发送范例。

事实上,上述客户端的TTimer控件是完全没有必要使用的。

  当我们对IdUDPClient使用Broadcast方法后,一旦与服务端通讯成功,IdUDPClient自动会得到来自服务端的返回值。

  如果通讯失败,在IdUDPClient.ReceiveTimeout所设定的事件后终止响应,所以我们可以吧延迟事件稍微设长一点。

  于是客户端代码可以简单的写成:

如此即可完成与服务端的通讯。

  =======================================================================

  关于网络中查找服务器主机的问题,似乎可以使用UDP广播的方式查找。

  先看代码:

这样在IpList中就会不断的有主机的IP地址被加入进来了。

  但是实际情况是这样的:

  由于使用了TTimer控件,我这里设置了Interval:5000,如果设置过小会因为线程大量占用而严重影响主程序正常工作,不知道有什么办法来解决这个问题。还有,当网络中没有服务器的任何响应时客户端也会出现假死现象,不知如何解决。

1 unitClientUnit;

2 interface

3 uses

4  Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,

5  Dialogs,StdCtrls,ExtCtrls,IdBaseComponent,IdComponent,IdUDPBase,

6  IdUDPClient;

7 type

8  TClientForm=class(TForm)

9   Label1:TLabel;

10   Edit1:TEdit;

11   Button1:TButton;

12   Label2:TLabel;

13   Edit2:TEdit;

14   IdUDPClient1:TIdUDPClient;

15   Timer1:TTimer;

16   procedureButton1Click(Sender:TObject);

17   procedureFormCreate(Sender:TObject);

18   procedureTimer1Timer(Sender:TObject);

19  private

20   {Privatedeclarations}

21  public

22   {Publicdeclarations}

23  end;

24 var

25  ClientForm:TClientForm;

26 implementation

27 {$R*.dfm}

28 procedureTClientForm.Button1Click(Sender:TObject);

29 begin

30  IdUDPClient1.Broadcast(Edit1.Text,3030);

31  Timer1.Enabled:=True;

32 end;

33 procedureTClientForm.FormCreate(Sender:TObject);

34 begin

35  Timer1.Enabled:=False;

36  Edit2.ReadOnly:=True;

37 end;

38 procedureTClientForm.Timer1Timer(Sender:TObject);

39 begin

40  Edit2.Text:=IdUDPClient1.ReceiveString(-1);

41  Timer1.Enabled:=False;

42 end;

43 end.

44

如此实现简单的UDP协议下局域网通讯。

  ===================================================

  但是很快我又发现,上面的代码在本机虽然能够正常执行,分别位于2台电脑时会发生无法接收服务器响应的现象。

  究其原因可能是客户程序用户界面“冻结”的缘故。

  于是在服务端和客户端都加上TIdAntiFreeze以解决上面发生的现象(尤其是客户端)。

  服务端:

1 unitServerUnit;

2 interface

3 uses

4  Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,

5  Dialogs,IdBaseComponent,IdComponent,IdUDPBase,IdUDPServer,StdCtrls,

6  IdSocketHandle,IdGlobal;

7 type

8  TServerForm=class(TForm)

9   Label1:TLabel;

10   Edit1:TEdit;

11   Label2:TLabel;

12   Edit2:TEdit;

13   Label3:TLabel;

14   Edit3:TEdit;

15   IdUDPServer1:TIdUDPServer;

16   procedureIdUDPServer1UDPRead(AThread:TIdUDPListenerThread;AData:TBytes;

17    ABinding:TIdSocketHandle);

18   procedureFormCreate(Sender:TObject);

19  private

20   {Privatedeclarations}

21  public

22   {Publicdeclarations}

23  end;

24 var

25  ServerForm:TServerForm;

26 implementation

27 {$R*.dfm}

28 procedureTServerForm.FormCreate(Sender:TObject);

29 begin

30  IdUDPServer1.DefaultPort:=3030;

31  IdUDPServer1.Active:=True;

32  Edit1.ReadOnly:=True;

33  Edit2.ReadOnly:=True;

34  Edit3.ReadOnly:=True;

35 end;

36 procedureTServerForm.IdUDPServer1UDPRead(AThread:TIdUDPListenerThread;

37  AData:TBytes;ABinding:TIdSocketHandle);

38 begin

39  Edit1.Text:=ABinding.PeerIP;

40  Edit2.Text:=IntToStr(ABinding.PeerPort);

41  Edit3.Text:=BytesToString(AData);

42  IdUDPServer1.Send(ABinding.PeerIP,ABinding.PeerPort,TimeToStr(Time)+'=>Serverreceivedthemessage!');

43 end;

44 end.

45

然后新建客户端如下图所示:

  注意:为了让客户端能实时监控服务端发回来的确定消息,使用了TTimer控件,Interval设置为250毫秒。