Драконограф писал(а):
Преимущество в первую голову эргономическое (разгрузка восприятия читателя)
Эквивалентные фрагменты кода на Оберон-е и ДРАКОНЕ-е, текстовый код в один экран не вмещается и весьма трудночитаем, схема выглядит значительно эргономичнее:
Код:
BEGIN {ACTIVE}
Dr010Vtk := Dr010Vtk0060;
WHILE Dr010Vtk # Dr010VtkExit DO
CASE Dr010Vtk OF
| Dr010Vtk0060:
(* Init *)
NEW(receiveBuf,
Base.MaxUDPDataLen);
NEW(sendBuf, 0);
NEW(clients);
NEW (users);
running := TRUE;
terminated := FALSE;
Dr010Vtk := Dr010Vtk0073
| Dr010Vtk0073:
(* Packet receive *)
IF running THEN
CheckKeepAlive(clients);
s.Receive (receiveBuf^, 0,
Base.MaxUDPDataLen,
1, ip, port, len, res);
IF (res = UDP.Ok) & (len > 0) THEN
receiveBufOffset := 0;
(* Version check *)
IF Base.BufGetInt(receiveBuf, receiveBufOffset) = Base.VERSION THEN
Dr010Vtk := Dr010Vtk0088
ELSE
Dr010Vtk := Dr010Vtk0073
END; (* IF *)
ELSE
Dr010Vtk := Dr010Vtk0073
END; (* IF *)
ELSE
Dr010Vtk := Dr010Vtk0066
END; (* IF *)
| Dr010Vtk0088:
(* Authentication *)
command := Base.BufGetInt(receiveBuf,
receiveBufOffset);
seqNum := Base.BufGetInt(receiveBuf,
receiveBufOffset);
uin := Base.BufGetLInt(receiveBuf,
receiveBufOffset);
Utilities.IntToStr(seqNum, str1);
Utilities.Concat(" SeqNum: ", str1, str1);
Utilities.Concat(str1, " Command: ", str1);
Utilities.IntToStr(uin, str2);
Utilities.Concat("User ID: ", str2, str2);
Utilities.Concat(str2, str1, str1);
Base.CommandDecode(command, str2);
Utilities.Concat(str1, str2, str1);
Log(AosEvents.Information, 0, str1, FALSE);
IF FindClient(clients, uin, client) THEN
(* Additional check *)
IF (IP.AdrsEqual(client.ip, ip)) & (client.port = port) THEN
Dr010Vtk := Dr010Vtk0098
ELSE
Dr010Vtk := Dr010Vtk0073
END; (* IF *)
ELSE
CASE command OF
| Base.LOGIN:
password :=
Base.BufGetString (receiveBuf,
receiveBufOffset);
IF users.PasswordCorrect(uin, password) THEN
NEW(client);
client.ip := ip;
client.port := port;
client.uin := uin;
client.inSeqNum := seqNum;
client.outSeqNum := 0;
Kernel.SetTimer(client.keepAliveTimer,
Base.clientKeepAliveAwait);
clients.Add(client);
Server_LoginReply(client, sendBuf, s);
MulticastStatus(clients, client,
Base.USER_ONLINE, sendBuf, s);
END; (* IF *)
| Base.NEW_USER_REG:
password := Base.BufGetString(receiveBuf,
receiveBufOffset);
shortName := Base.BufGetString(receiveBuf,
receiveBufOffset);
fullName := Base.BufGetString(receiveBuf,
receiveBufOffset);
eMail := Base.BufGetString(receiveBuf,
receiveBufOffset);
user := users.Add(password, shortName,
fullName, eMail);
Server_NewUserReply(ip, port, user.uin,
seqNum, sendBuf, s);
ELSE (* CASE *)
END; (* CASE *)
Dr010Vtk := Dr010Vtk0073
END; (* IF *)
| Dr010Vtk0098:
(* Packet handle *)
IF command = Base.ACK THEN
IF Base.SeqNumInACKList( client.ACKList, seqNum, ACKReq) THEN
client.ACKList.Remove(ACKReq);
END; (* IF *)
ELSE
IF Base.isNextSeqNum( seqNum, client.inSeqNum) THEN
client.inSeqNum := seqNum;
CASE command OF
| Base.SEND_MESSAGE:
Server_ACK(client, sendBuf, s);
receiverUin := Base.BufGetLInt(
receiveBuf, receiveBufOffset);
messageType := Base.BufGetInt(
receiveBuf, receiveBufOffset);
message := Base.BufGetString(
receiveBuf, receiveBufOffset);
dt := Dates.Now();
IF receiverUin = 0 THEN
MulticastMessage(
clients, client, dt,
messageType,
message,
sendBuf, s);
ELSE
IF FindClient(clients, receiverUin, receiver) THEN
Server_ReceiveMessage(
client, receiver, dt,
messageType, message,
sendBuf, s);
END; (* IF *)
END; (* IF *)
| Base.KEEP_ALIVE:
Server_ACK(client, sendBuf, s);
Kernel.SetTimer(
client.keepAliveTimer,
Base.clientKeepAliveAwait);
| Base.INFO_REQ:
receiverUin := Base.BufGetLInt(
receiveBuf, receiveBufOffset);
user := users.Find(receiverUin);
IF user # NIL THEN
Server_InfoReply(
client, user,
sendBuf, s);
END; (* IF *)
| Base.SEND_TEXT_CODE:
Server_ACK(client, sendBuf, s);
textCode := Base.BufGetString(
receiveBuf, receiveBufOffset);
IF textCode^ = "USER_DISCONNECTED" THEN
MulticastStatus(clients,
client, Base.USER_OFFLINE,
sendBuf, s);
clients.Remove(client);
END; (* IF *)
ELSE (* CASE *)
END; (* CASE *)
END; (* IF *)
END; (* IF *)
Dr010Vtk := Dr010Vtk0073
| Dr010Vtk0066:
(* End *)
users.Store;
FinalizeClients(clients);
clients.Clear;
BEGIN {EXCLUSIVE}
terminated := TRUE
END;
Dr010Vtk := Dr010VtkExit
ELSE (* CASE *)
END (* CASE *)
END (* WHILE *)
END Instance;