UDP é um protocolo de transporte de dados que se caracteriza por não garantir a entrega dos dados, o que permite entregar rapidamente os dados. Um uso frequente para UDP é transmissão de áudio ou vídeo, que é um caso onde a perda de um pacote de dados não compromete o resultado final.
Uma outra característica do protocolo UDP é a possibilidade de transmitir um mesmo pacote de dados para todas as máquina da rede em uma única operação, o que é conhecido como broadcast. Nesse caso, os dados são enviados por UDP para um endereço especial da rede que replicará o mesmo pacote de dados para todos os endereços da mesma subrede.
Um uso possível seria localizar numa rede local todas as máquinas que estão executando seu programa. Para isso, uma cópia do programa poderia iniciar um broadcast na rede pedindo que todas as outras cópias (em uso) do programa se identifiquem, por exemplo, informando o nome da máquina e o IP.
Usando os componentes TIdUDPClient e TIdUDPServer, o código seria algo assim:
1 type
2 TSeuForm = class(...)
3 // coloque um TIdUDPClient e TIdUDPServer no form
4 // por exemplo...
5 UDPClient: TIdUDPClient;
6 UDPServer: TIdUDPServer;
7 ...
8 procedure FormCreate(Sender: TObject);
9 procedure FormDestroy(Sender: TObject);
10 procedure UDPServerUDPRead(Sender: TObject; AData: TStream;
11 ABinding: TIdSocketHandle);
12 ...
13 private
14 procedure Ping;
15 ...
16
17 const
18 NOSSA_PORTA = 49152; // pode ser qualquer valor entre 49152 e 65535
19
20 // rotina de PING
21 // em algum lugar do programa isso é executado
22 procedure TSeuForm.Ping;
23 var
24 S: string;
25 IP: string;
26 X: Integer;
27 begin
28 // não queremos responder nosso próprio comando
29 UDPServer.Active := False;
30
31 // timeout da resposta, em milissegundos
32 UDPClient.ReceiveTimeout := 5000;
33
34 // manda o comando para todas as máquinas da rede
35 UDPClient.Broadcast('PING', NOSSA_PORTA);
36
37 // espera pela resposta
38 while True do begin
39
40 S := UDPClient.ReceiveString(IP, X);
41 if S = '' then begin
42 // ocorreu timeout
43 Break;
44 end;
45 // faz alguma coisa com os dados...
46 // - S tem o nome da máquina que respondeu
47 // - IP tem o IP da máquina que respondeu
48 end;
49
50 UDPServer.Active := True;
51 end;
52
53 // evento OnUDPRead do UDPServer
54 procedure TSeuForm.UDPServerUDPRead(Sender: TObject; AData: TStream;
55 ABinding: TIdSocketHandle);
56 var
57 Server: TIdUDPServer;
58 S: String;
59 begin
60 Server := Sender as TIdUDPServer;
61
62 // recupera o que recebeu
63 SetLength(S, AData.Size);
64 AData.Read(S[1], AData.Size);
65
66 // é o nosso comando de PING?
67 if S = 'PING' then begin
68
69 // envia a resposta
70 S := Server.LocalName;
71 ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, S[1], Length(S));
72 end;
73 end;
74
75 // evento OnCreate do form
76 procedure TSeuForm.FormCreate(Sender: TObject);
77 begin
78 UDPServer.DefaultPort := NOSSA_PORTA;
79 UDPServer.Active := True;
80 ...
81 end;
82
83 // evento OnDestroy do form
84 procedure TSeuForm.FormDestroy(Sender: TObject);
85 begin
86 UDPServer.Active := False;
87 ...
88 end;
Para evitar conflitos com outros programas e serviços do Windows, procure escolher uma porta (linha 18) entre 49152 e 65535. Independente da porta escolhida, lembre-se que essa porta precisa estar liberada para UDP no seu firewall.
O valor de timeout usado na rotina de ping (linha 32) precisa ser ajustado de acordo com o tamanho da rede. Um valor muito pequeno pode fazer com que a rotina de ping desista antes que todas as máquinas respondam e um valor muito alto pode congelar momentaneamente o programa. Não tem outra forma de aguardar pela resposta das máquinas já que, a princípio, a rotina não sabe quantas máquinas vão responder.
Broadcast deve ser usado com moderação. O broadcast utiliza um endereço especial da rede para transmitir os dados que faz com que o mesmo pacote de dados seja enviado a todos os endereços possíveis da rede. Como isso consome recursos da rede, não é boa idéia utilizar isso sem que seja absolutamente necessário. É tentador colocar a rotina de ping num timer que executa a cada segundo, mas o administrador da sua rede não vai ficar muito feliz com essa idéia.
Eu não entendo muito de redes, mas é bom saber que alguns roteadores podem impedir o broadcast.
Links relacionados