Исходный код
Сервер состоит из двух частей, Server.pas и BSOD.pas. BSOD.pas содержит форму, которая используется для показа BSOD экрана. BSOD.pas не содержит Indy кода и поэтому не рассматривается здесь.
Server.pas – это главная форма приложения и содержит один UDP сервер. Свойство port установлено в 6001 и свойство active установлено в True. Когда приложение запускается, то оно немедленно начинает слушать порт для входящих UDP пакетов.
Как ранее обсуждалось UDP подобен пейджеру. Поскольку ему не требуется соединение для приема данных. Пакеты данных просто появляются как один кусок. Для каждого принятого UDP пакета, UDP сервер возбуждает событие OnUDPRead. Больше никаких других событий не требуется для реализации UDP сервера. Когда возбуждается событие OnUDPRead, полный пакет уже принят и готов к использованию.
Событию OnUDPRead передаются три аргумента:
1. ASender: TObject – это компонент, который возбудил данное событие. Это применимо только если будет создано несколько UDPServers серверов и используют один и тот же метод для события. Это очень редко нужно.
2. AData: TStream – это основной аргумент и он содержит сам пакет. UDP пакеты могут содержать текст и/или двоичные данные. Поэтому Indy предоставляет их в виде потока. Для доступа к данным, просто используйте методы read класса TStream.
3. ABinding: TIdSocketHandle – этот аргумент пригоден для получения расширенной информации. Это востребовано, если используется связывание (bindings). Вот пример как выглядит событие OnUDPRead в RBSOD сервере:
procedure TformMain.IdUDPServer1UDPRead(Sender: TObject; AData: TStream; ABinding: TIdSocketHandle);
var
LMsg: string;
begin
if AData.Size = 0 then
begin
formBSOD.Hide;
end
else
begin
// Move from stream into a string
SetLength(LMsg, AData.Size);
AData.ReadBuffer(LMsg[1], Length(LMsg));
//
formBSOD.ShowBSOD(Copy(LMsg, 3, MaxInt),
Copy(LMsg, 1, 1) = 'T',
Copy(LMsg, 2, 1) = 'T');
end;
end;
Обратим внимание, что оператор if проверяет на нулевую длину. Это вполне легально посылать и принимать пустые UDP пакеты. В данном случае это используется для сигнализации серверу о снятии BSOD.
Если размер не равен 0, то данные копируются в локальную строковую перемену с помощью TStream.ReadBuffer.
UDP сервер не использует отдельного потока для каждого пакета, поскольку события OnUDPRead возникают последовательно. По умолчанию OnUDPRead возникает в главном кодовом потоке и формы и другие GUI органы управления могут использоваться безопасно.