O transporte que um desenvolvedor escolhe molda a sensação de jogar um jogo de navegador multijogador. Veja como os canais de dados WebRTC e WebSockets diferem e quando cada um ganha seu lugar.
Todo jogo de navegador multijogador precisa mover pequenas quantidades de dados entre os jogadores muitas vezes por segundo, desde posições e entradas até acertos e alterações de pontuação. O navegador oferece duas maneiras principais de transportar esse tráfego, e elas se comportam de maneira muito diferente quando uma correspondência é preenchida. Um deles é executado através de um servidor sobre TCP. O outro conecta os jogadores mais diretamente através do UDP. Escolher entre eles antecipadamente é muito mais fácil do que trocar mais tarde.
Dois transportes, dois modelos de rede
Um WebSocket mantém uma única conexão de longa duração aberta entre um cliente e um servidor e funciona em TCP, que entrega mensagens como um fluxo ordenado e estrito. WebRTC funciona de maneira diferente. Seus canais de dados movem informações por UDP e podem envie dados do jogo sem esperar a chegada de pacotes anterioresportanto, um pacote lento ou ausente não paralisará aqueles que estão por trás dele.
Como isso fica no código
A lacuna aparece em apenas algumas linhas. Um WebSocket abre um fluxo ordenado e confiável em uma única conexão de servidor:
const socket = new WebSocket("wss://example.com/game");
socket.onopen = () => {
socket.send(JSON.stringify({ type: "move", x: 12, y: 4 }));
};
socket.onmessage = (e) => updateGame(JSON.parse(e.data));
Um canal de dados WebRTC estabelece um link direto entre os jogadores e pode descartar as garantias que impedem um jogo rápido, enviando mensagens desordenadas e sem reenviar as que faltam:
const peer = new RTCPeerConnection();
const channel = peer.createDataChannel("game", {
ordered: false,
maxRetransmits: 0,
});
channel.onopen = () => {
channel.send(JSON.stringify({ type: "move", x: 12, y: 4 }));
};
channel.onmessage = (e) => updateGame(JSON.parse(e.data));
A sinalização que permite que dois pares se encontrem é deixada de fora aqui e, na prática, geralmente é executada em um WebSocket antes da abertura do canal de dados.
Por que os jogos em tempo real se preocupam com o UDP
A diferença está em como cada protocolo trata um pacote perdido. O TCP garante a ordem, de modo que um pacote descartado retém tudo o que está na fila atrás dele, um problema conhecido como bloqueio head-of-line. Um canal de dados WebRTC conecta dois pares diretamente por UDP, usando SCTP sobre DTLS, e pode ser executado em modo confiável ou não confiável, o que um WebSocket simples não pode fazer. É por isso que a sincronização do estado do jogo de baixa latência sem um servidor no meio frequentemente é executada em canais de dados, porque as atualizações de posição mais recentes continuam fluindo mesmo quando uma mais antiga nunca chega.
Onde os WebSockets se mantêm firmes
O problema é a confiabilidade. Como o TCP reenvia tudo o que está faltando e o entrega em ordem, um WebSocket é a escolha mais segura quando todas as mensagens precisam chegar intactas, como bate-papo, alterações de inventário ou uma pontuação final confirmada. Como afirma uma comparação lado a lado, o UDP é mais rápido, mas aceita que alguns pacotes serão perdidos, enquanto o TCP é mais lento para recuperar, mas nunca descarta uma mensagem.
Por que os dois costumam enviar juntos
Na maioria dos sistemas de produção, os dois são parceiros e não rivais. Uma configuração comum usa um WebSocket como canal de sinalização que ajuda dois pares a se descobrirem e trocarem detalhes da conexão antes que o link WebRTC seja aberto, após o qual o canal de dados transporta o tráfego rápido do jogo. Por si só, as viagens de ida e volta do servidor WebSocket geralmente chegam a dezenas de milissegundos, o que é bom para menus, matchmaking e mensagens.
A compensação ponto a ponto em escala
As conexões diretas têm um teto. Eles funcionam bem para partidas pequenas, mas não ultrapassam um punhado de jogadores, de modo que lobbies grandes tendem a recorrer a um retransmissor ou a um servidor oficial. Em vez disso, uma abordagem baseada em servidor pode manter milhares de conexões em uma única instância e crescer para fora, e é por isso que estruturas WebSocket como Socket.IO permanecem comuns para salas maiores.
Como isso funciona na produção
A rota ponto a ponto acarreta mais um custo que uma comparação de protocolo raramente menciona. O WebRTC ainda precisa de sinalização e passagem de NAT antes que dois jogadores possam se conectar, e é por isso que poucas equipes pequenas o constroem do zero. As empresas que mais investiram na solução disso são aquelas que já rodam jogos em tempo real em grande volume. Poki, a maior plataforma de jogos na web do mundo, é uma delas.
Do lado do jogador, Jogos .io de Poki compõem um catálogo de mais de 35 títulos de navegador onde dez ou mais jogadores compartilham uma única partida ao vivo.
A empresa também abriu o código-fonte de sua resposta para esse problema de rede. Sua biblioteca, Netlib, usa canais de dados WebRTC para abrir links UDP diretos entre jogadores e oferece sinalização gratuita e servidores STUN/TURN para que um jogo não precise executar seu próprio back-end em tempo real, uma ideia que a equipe compara à Steam Networking Library reconstruída para a web.
Para um jogo de cartas baseado em turnos ou uma sobreposição de bate-papo, um WebSocket ainda é o padrão sensato, e o guia do SitePoint para construindo aplicativos em tempo real em WebSockets em Node.js é um lugar sólido para começar. Uma arena de reação de contração, onde alguns milissegundos decidem o resultado, é onde os canais de dados WebRTC ganham seu sustento. De qualquer forma, crie um protótipo da camada de rede antecipadamente, porque o transporte molda a arquitetura de um jogo mais do que qualquer outra decisão.
Source link




