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

 

 

代码如下: 

 

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

 

 

 

客户端:  

事实上,上述客户端的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毫秒。 

 

posted on 2010-12-14 11:19  Delphi2010_老赵  阅读(7779)  评论(0编辑  收藏  举报

导航