Mapeando Grupos e Conexões

· Recursos

Em um post anterior, apresentei o novo recurso de Grupos nos Servidores WebSocket. Neste post, mostrarei como combinar os Grupos WebSocket com as Conexões de Cliente para identificar e armazenar os dados do usuário em uma conexão de cliente.

A biblioteca sgcWebSockets permite criar seus próprios objetos e vinculá-los a uma classe TsgcWSConnection, para que você possa acessar seu objeto personalizado a qualquer momento quando uma nova mensagem for recebida, quando o cliente se desconectar... Agora você pode combinar a facilidade de uso dos Grupos e dos Objetos Personalizados para criar aplicações avançadas facilmente.

Autenticar Usuários

O servidor será configurado para aceitar apenas conexões de usuários autenticados, portanto, primeiro ative a Autenticação no lado do servidor e depois configure o evento OnAuthentication para autenticar a conexão recebida pelo servidor. Os usuários geralmente são armazenados em um banco de dados; neste exemplo, eles estão codificados diretamente para simplificar.

Server.Authentication.Enabled := True;
Server.Authentication.Basic.Enabled := True; 

Veja abaixo um exemplo de código: primeiro avalie se o Usuário/Senha são conhecidos; se corretos, crie uma nova instância da classe TsgcUser onde os dados do usuário são armazenados, preencha as propriedades e atribua à propriedade Connection.Data. Desta forma, você pode acessar os dados do usuário quando receber uma mensagem dele, quando se desconectar... 

type
  TsgcUser = class
  private
    FAge: Integer;
    FDepartment: string;
    FPhone: string;
    FUsername: string;
  public
    property Username: string read FUsername write FUsername;
    property Department: string read FDepartment write FDepartment;
    property Phone: string read FPhone write FPhone;
    property Age: Integer read FAge write FAge;
  end;
procedure OnServerAuthentication(Connection: TsgcWSConnection; aUser, 
  aPassword: string; var Authenticated: Boolean);
var
  oUser: TsgcUser;
begin
  if (aUser = 'user-1') and (aPassword = 'password-1') then
  begin
    Authenticated := True;
    oUser := TsgcUser.Create;
    oUser.Username := 'Mark';
    oUser.Phone := '+55431588744134';
    oUser.Department := 'Sales';
    oUser.Age := 22;
    Connection.Data := oUser;
  end
  else
    Authenticated := False;
end; 

Assim que o usuário é Autenticado, o evento OnConnect será disparado; aqui você pode adicionar o usuário a um Grupo. Nesta demonstração, a propriedade Department do usuário será usada como nome do Grupo. Você pode adicionar uma conexão a mais de 1 grupo, basta chamar o método Groups.Add quantas vezes forem necessárias.

procedure OnServerConnect(Connection: TsgcWSConnection);
begin
  Server.Groups.Add(TsgcUser(Connection.Data).Department, Connection);
end; 

Quando o cliente se desconecta, a classe de conexão é removida automaticamente da propriedade Groups, portanto, não é necessário remover manualmente, pois isso é feito automaticamente. 

Usando Eventos

A propriedade Groups tem 2 eventos para notificar sempre que um usuário foi adicionado a um grupo ou quando foi removido.

OnClientAdded: quando uma nova conexão foi adicionada a um grupo.

OnClientRemoved: quando uma conexão existente foi removida de um grupo.

Você pode configurar esses eventos antes de o Servidor ser iniciado. No exemplo a seguir, enviamos uma mensagem a todos os membros do grupo informando que um novo membro foi adicionado ou que um membro existente se desconectou.

Server.Groups.OnClientAdded := OnClientAddedEvent;
Server.Groups.OnClientRemoved := OnClientRemovedEvent;
procedure OnClientAddedEvent(Sender: TObject; const aGroup:
    TsgcWSServerGroupItem; const aConnection: TsgcWSConnection);
var
  vMessage: string;
begin
  vMessage := TsgcUser(aConnection.Data).Username + ' has logged in.';
  aGroup.BroadCast(vMessage);
end;
procedure TForm16.OnClientRemovedEvent(Sender: TObject; const aGroup:
    TsgcWSServerGroupItem; const aConnection: TsgcWSConnection);
var
  vMessage: string;
begin
  vMessage := TsgcUser(aConnection.Data).Username + ' has disconnected.';
  aGroup.BroadCast(vMessage);
end; 

Enviando Mensagens

Você pode usar os Grupos para transmitir mensagens a grupos específicos, a múltiplos grupos... veja abaixo alguns exemplos.

// All members
Server.Groups.Broadcast('*', 'Hello All Members.');
// Only group "admin"
Server.Groups.Broadcast('admin', 'Hello Admin Members.');
// All sales groups (sales/asi, sales/europe, sales/america...)
Server.Groups.Broadcast('sales/*', 'Hello Sales Members.');
// Only group "accounting" (must exists!!!)
Server.Groups.Group['accounting'].Broadcast('Hello Accounting Members.'); 

Veja abaixo o código-fonte das aplicações de Servidor e Cliente, bem como os binários compilados para Windows.