- Filtro de Palavras: Um filtro de palavras proibidas, carregado de um arquivo
forbidden_words.txt, censura mensagens antes de serem distribuídas. - Logging Thread-Safe: Eventos importantes do servidor (conexões, desconexões, mensagens) são registrados em um arquivo de log de forma segura.
LPII-projeto-final/
|
|-- bin/ # Contém os executáveis compilados e arquivos de log
|-- build/ # Contém os arquivos objeto (.o) temporários da compilação
|-- include/ # Contém os arquivos de cabeçalho (.hpp)
| |-- chat/
| `-- utils/
|-- src/ # Contém os arquivos de implementação (.cpp)
| |-- chat/
| |-- utils/
| `-- main.cpp
|-- scripts/ # Contém scripts para automação de testes
|-- forbidden_words.txt # Arquivo de configuração do filtro de palavras
|-- Makefile # Arquivo de build para compilação
`-- README.md
O diagrama abaixo ilustra o fluxo de comunicação para os cenários de conexão de um cliente com um servidor,
usando como exemplo uma mensagem:

-
Requisito 1: Servidor TCP concorrente aceitando múltiplos clientes.
- Mapeamento: Implementado na classe
Server, métodorun(). O servidor entra em um loopwhile(true)que aguarda emaccept(). Para cada nova conexão, umastd::threadé criada para executar um objetoClientHandler, permitindo que o servidor aceite novos clientes concorrentemente.
- Mapeamento: Implementado na classe
-
Requisito 2: Cada cliente atendido por thread; mensagens retransmitidas para os demais (broadcast).
- Mapeamento: A lógica de atendimento é encapsulada na classe
ClientHandler. O métodohandle_client()recebe mensagens de um cliente e implementa o broadcast chamandoshared_state.get_all_clients()para obter a lista de destinatários e enviando a mensagem em um loop.
- Mapeamento: A lógica de atendimento é encapsulada na classe
-
Requisito 3: Logging concorrente de mensagens (usando libtslog).
- Mapeamento: A biblioteca
libtslogé representada pela classeLogger, que utiliza o padrão Produtor-Consumidor. Múltiplas threadsClientHandlerchamam o métodolog()de forma segura (protegido porstd::mutex) para enfileirar mensagens, enquanto uma única thread interna (writer_thread_func) escreve no arquivo.
- Mapeamento: A biblioteca
-
Requisito 4: Cliente CLI: conectar, enviar/receber mensagens.
- Mapeamento: Implementado na classe
Client. O métodorun()cria duas threads:send_messages()para ler a entrada do usuário (std::getline) ereceive_messages()para aguardar dados do servidor (recv()), permitindo comunicação simultânea.
- Mapeamento: Implementado na classe
-
Requisito 5: Proteção de estruturas compartilhadas (lista de clientes, histórico).
- Mapeamento: A proteção é realizada pela classe
SharedState. Todos os métodos que acessam os dados compartilhados (clientsemessage_history) utilizam umstd::lock_guard<std::mutex>para garantir exclusão mútua e prevenir condições de corrida.
- Mapeamento: A proteção é realizada pela classe
- Compilador C++17 ou superior (g++)
make- Biblioteca
pthread
-
Compilar o projeto: A partir da pasta raiz, execute:
make
-
Iniciar o Servidor: Em um terminal, execute:
./bin/chat_app server <porta>
Exemplo:
./bin/chat_app server 8080 -
Iniciar um Cliente Interativo: Em um novo terminal, execute:
./bin/chat_app client <ip_do_servidor> <porta>
Exemplo:
./bin/chat_app client 127.0.0.1 8080 -
Limpar arquivos compilados:
make clean
Um script está disponível para simular múltiplos clientes automáticos (não-interativos).
- Com o servidor rodando, abra um novo terminal.
- Execute o script:
./scripts/test_clients.sh
# Obs:
Ao fechar o server com uma porta, o windows não vai fechar a porta imediatamente, então pode ser que o usuário não consiga criar um servidor com a mesma porta antes de um tempo de espera (entre 30 - 180 segundos)