首先新建服务端。
如下图所示建立工程:
代码如下:
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毫秒。
|
请发表评论