Files
pitiupi/docs/documentation/05_udp_multicast.md
T
Gabriel Felipe Souza SantosandCursor e84aba2f4e feat(run): abre o Java da placa real e guarda dados no clone
Linux, WSL e Windows usam o mesmo run --all, e plugins, cache e logs ficam em .pitiupi na raiz do projeto.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-11-03 23:52:08 -03:00

5.1 KiB
Raw Blame History

Comunicação UDP

Teoria: UDP envia datagramas sem conexão; multicast replica um pacote na LAN para todos os membros do grupo. No Pitiupi: presença e muitas mensagens de plugins usam o mesmo MulticastSocket na porta do login. Limitação: sem garantia de entrega nem ordem — plugins com imagens grandes devem considerar perda e MTU.

A classe SocketUDP é responsável pela comunicação UDP da aplicação.

Ela utiliza um MulticastSocket associado à porta configurada pela aplicação e ingressa no grupo multicast 224.0.0.3. Por ser baseada em UDP, a comunicação não estabelece uma conexão permanente entre os peers.

A classe estende Thread, mantendo um processo contínuo de recepção de datagramas enquanto a aplicação está em execução.

O SocketUDP suporta dois modos de envio:

  • multicast, destinado ao grupo de peers
  • unicast, destinado diretamente ao endereço IP de um peer específico

Inicialização

Durante sua inicialização, o SocketUDP:

  1. obtém o endereço do grupo multicast;
  2. cria um MulticastSocket na porta escolhida no login (mesma porta TCP da sala);
  3. configura os buffers de envio e recepção;
  4. habilita o reuso do endereço;
  5. define o TTL (padrão 1, alterável na aba Configurações) e a interface de saída;
  6. ingressa no grupo multicast.

O tamanho dos buffers de comunicação é configurado para 256000 bytes.

Envio de mensagens UDP

O SocketUDP suporta dois modos de envio de mensagens: multicast e unicast, ambos baseados no mesmo mecanismo interno de criação e envio de DatagramPacket.

O método sendMulticast() envia uma mensagem para o grupo multicast da aplicação. Nesse caso, o DatagramPacket é direcionado ao endereço multicast configurado, permitindo que todas as instâncias participantes do grupo recebam a mensagem simultaneamente.

Já o método sendUnicast() permite enviar uma mensagem diretamente para um peer específico. Nesse caso, o DatagramPacket é direcionado ao endereço IP informado pelo chamador, mantendo a mesma porta utilizada pela aplicação.

Ambos os métodos são, na prática, abstrações de um único mecanismo interno de envio, que utiliza o mesmo processo de criação e envio de DatagramPacket por baixo dos panos. A diferença entre eles está apenas no endereço de destino: enquanto o multicast utiliza o grupo compartilhado, o unicast direciona o pacote a um IP específico.

Recepção de mensagens

O método receive() mantém um loop aguardando novos datagramas.

Ao receber uma mensagem, o SocketUDP inicialmente tenta identificar se os dados correspondem a uma HeartbeatMessage.

O processamento segue o seguinte fluxo:

  1. O datagrama é recebido pelo MulticastSocket.
  2. Os dados recebidos são analisados pelo método tryParseHeartbeat().
  3. Caso seja identificada uma HeartbeatMessage, ela é encaminhada ao HeartbeatManager, juntamente com o endereço IP de origem.
  4. Caso não seja um heartbeat, a mensagem é encaminhada para todos os plugins carregados.
  5. Cada plugin decide se a mensagem recebida pertence à sua funcionalidade.

Essa separação mantém as mensagens de infraestrutura, como heartbeat, sob responsabilidade do núcleo da aplicação, enquanto as mensagens específicas das funcionalidades são processadas pelos plugins.

Identificação de mensagens de heartbeat

O método tryParseHeartbeat() tenta desserializar os dados recebidos e verificar se o objeto resultante é uma instância de HeartbeatMessage.

Caso a mensagem não possa ser desserializada ou não corresponda ao tipo esperado, o método retorna null. Nesse caso, a mensagem é tratada como uma mensagem destinada aos plugins.

Encerramento

O método close() interrompe a execução do processo de recepção, remove a aplicação do grupo multicast e fecha o MulticastSocket.

A variável running é utilizada para sinalizar que o processo de recepção deve ser encerrado.

Interface de rede

LocalNetworkInfo.preferredNetworkInterface() escolhe a interface para o multicast: Ethernet antes de Wi‑Fi; em cabo APIPA (169.254.*) prioriza esse endereço. Em sala só Wi‑Fi, a interface wireless é usada normalmente. Requisito: peers na mesma sub-rede e multicast permitido — ver appendix_portas_e_multicast.md.

Sequência didática (plugin → peer B)

sequenceDiagram
    participant UI as Plugin_UI
    participant Disp as MessageDispatcher
    participant CM as ConnectionManager
    participant UDP as SocketUDP
    participant LAN as LAN_UDP
    participant UDPb as SocketUDP_peerB
    participant PM as PluginManager_peerB

    UI->>Disp: enviar Message + modo + destino
    Disp->>CM: send UDP
    CM->>UDP: sendUnicast ou sendMulticast
    UDP->>LAN: DatagramPacket
    LAN->>UDPb: receive
    UDPb->>PM: byte[] desserializado
    PM->>UI: receiveMessage no plugin

Falhas comuns: firewall bloqueando UDP na porta do login; portas diferentes entre peers; isolamento de clientes no Wi‑Fi; um processo dentro do WSL e o outro no Java do Windows. Onde abrir a janela: appendix_portas_e_multicast.md.