From 36806646b52eb5c9551238fbf3bb5cdfe49a1660 Mon Sep 17 00:00:00 2001 From: allandantas21 <135276676+AllanDantas21@users.noreply.github.com> Date: Fri, 3 Oct 2025 18:13:42 -0300 Subject: [PATCH] adding basic architecture doc --- docs/Documentation.md | 38 ++++++++++++++++++++++++++++++++++++++ docs/img/flux.png | Bin 0 -> 37095 bytes srcs/server.cpp | 1 + 3 files changed, 39 insertions(+) create mode 100644 docs/Documentation.md create mode 100644 docs/img/flux.png diff --git a/docs/Documentation.md b/docs/Documentation.md new file mode 100644 index 0000000..84b89a6 --- /dev/null +++ b/docs/Documentation.md @@ -0,0 +1,38 @@ + +# Apresentando um Servidor IRC +IRC (Internet Relay Chat) é um protocolo de comunicação em tempo real que permite múltiplos usuários se conectarem a um servidor central para trocar mensagens em canais (salas) ou conversas privadas. + +# Arquitetura básica do projeto +O fluxo básico da implementação do servidor começa em ircserv, ele será o ponto de entrada de toda a aplicação, encapsulando as validações iniciais de inputs, signal handler, e tendo uma instância do Server, que é a classe responsável pela implementação de todo o core do servidor, como o polling não bloqueante, sockets, bind da porta e etc. + +A classe Server é o núcleo da aplicação, e seu ciclo de vida permanecerá ativo por toda a execução do programa, guardando os estados dos clientes e gerenciando o I/O. + +Cada Server guarda um vector com cada cliente sendo representado pela classe "Client", e cada instância de client tem a responsabilidade basicamente de guardar as informações do cliente, sendo quase toda composta com setters e getters, servindo quase como um mini banco de dados em runtime. + +Toda mensagem recebida de um client chega no server, e logo depois é passada para a classe "Parser", essa classe tem o único objetivo de implementar os métodos para tratar cada tipo de comando, como o PASS, NICK, USER e etc. + +E por último, temos a classe "Channel", que representa um canal dentro do nosso server, guardando as informações de operators e de clientes que estão no canal para fazermos o broadcast de cada mensagem enviada no canal para os demais clientes conectados. + +![alt text](./img/flux.png) + +# Configuração inicial do server +A configuração do servidor começa no método `ServerConfig()`, onde é criado o socket principal usando `socket(AF_INET, SOCK_STREAM, 0)`. Este socket é configurado para aceitar conexões TCP na família de endereços IPv4. + +O endereço do servidor é definido através da estrutura `sockaddr_in`, configurando a família de endereços como `AF_INET`, a porta através de `htons()` para conversão de byte order, e o endereço IP como `INADDR_ANY` para aceitar conexões de qualquer interface de rede. + +Após a criação do socket, são aplicadas configurações importantes através de `SetupSocketOptions()`: `SO_REUSEADDR` para permitir reutilização do endereço e `O_NONBLOCK` para tornar o socket não bloqueante, essencial para o funcionamento do polling. + +O socket é então vinculado à porta especificada através de `bind()` e colocado em modo de escuta com `listen()`, configurado para aceitar até `SOMAXCONN` conexões simultâneas. + +O sistema de polling é implementado usando a função `poll()` do sistema operacional. O servidor mantém um vector de estruturas `pollfd` que monitora todos os file descriptors ativos - tanto o socket principal quanto os sockets dos clientes conectados. Cada estrutura `pollfd` é configurada para monitorar eventos de entrada (`POLLIN`) e saída (`POLLOUT`). + +O loop principal em `WaitConnection()` fica aguardando eventos através de `poll()` com timeout infinito. Quando eventos são detectados, `HandlePollEvents()` processa cada file descriptor que tem eventos pendentes: novos clientes são aceitos no socket principal, dados são recebidos dos clientes existentes, e mensagens são enviadas quando o socket está pronto para escrita. + +# O que é I/O não bloqueante? +I/O não bloqueante é um conceito fundamental em programação de sistemas que permite que um programa continue executando outras tarefas enquanto aguarda operações de entrada e saída (como leitura de dados de um socket ou escrita em um arquivo). + +Em um sistema bloqueante tradicional, quando o programa tenta ler dados de um socket, ele "trava" e fica esperando até que os dados cheguem. Isso significa que o programa não pode fazer mais nada durante esse tempo - ele está literalmente bloqueado. + +No nosso servidor IRC, isso seria um problema sério. Imagine que temos 100 clientes conectados e um deles está enviando uma mensagem muito longa. Em um sistema bloqueante, o servidor ficaria parado esperando essa mensagem terminar, ignorando completamente os outros 99 clientes que podem estar tentando se conectar ou enviar mensagens. + +Em resumo, I/O não bloqueante transforma nosso servidor de um sistema que atende um cliente por vez em um sistema que pode gerenciar centenas de clientes simultaneamente. \ No newline at end of file diff --git a/docs/img/flux.png b/docs/img/flux.png new file mode 100644 index 0000000000000000000000000000000000000000..55b2cbeac2691b9b774ef1fa3ea14a80a3f8ec41 GIT binary patch literal 37095 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 Zspyucv-I9yJx6b