Vamos continuar a série de artigos sobre desenvolvimento de jogos. Nosso objetivo é mostrar como pensar, organizar, planejar e desenvolver jogos multiplayer em redes.
No primeiro artigo publicado aqui no iMasters, mostrei alguns fatos sobre o desenvolvimento de jogos. O segundo tratou sobre a arquitetura cliente-servidor.
No Fábrica de Jogos você pode ver também um artigo no qual eu falei sobre a camada OSI e o protocolo TCP. Cama OSI é um modelo geral de como funcionam as transferências de dados de um computador para outro. O TCP é um protocolo de transporte. Abordei como ele cria uma conexão com outro computador para ter certeza de que todos os dados chegaram corretamente.
Hoje veremos um outro protocolo: o UDP (User Datagram Protocol). Vamos compará-lo com o TCP, para que tenhamos critérios de quando usar um ou outro nos nossos jogos.
O protocolo UDP
Enquanto o TCP cria uma conexão e envia os dados como se nós estivéssemos escrevendo um arquivo, o UDP é mais direto: ele simplesmente envia os dados. Para enviar, nós definimos o computador destinatário e a porta por qual o destinatário estará esperando os dados. Assim, ele é simplesmente enviado, passando de computador a computador até chegar ao usuário, ou simplesmente ser perdido na imensidão da Internet. Sim, não existem garantias de que os dados cheguem ao destinatário no UDP.
Enquanto isso, no computador destinatário, ele estará esperando na porta especificada por qualquer dado que chegue por ela. Isso mesmo, quaisquer dados, de qualquer remetente. Afinal, diferente do TCP, não existe o conceito de conexão. Qualquer dado que chegue até o computador será aceito e o aplicativo vai interpretar o pacote. Isso servirá para ver se é ou não um pacote válido.
Como não é um protocolo que realiza confirmação de recebimento, ele pode ser perdido no caminho e nunca chegar. Isso ocorre principalmente quando a distância física percorrida é grande. Também não existe a garantia de que a ordem de chegada dos pacotes vai ser a mesma da saída. Eu posso enviar pacotes na ordem 1, 2, 3, 4 e 5 e o destinatário receber 2,3,5,1,4. Na prática, a tendência é chegar na ordem, principalmente se o roteamento dos pacotes se mantiver igual. Mas isso não é regra e é melhor não contar com isso.
Entretanto, uma garantia do UDP é de que se o pacote chegar, ele vai chegar 100%. Ou seja: se eu envio um pacote de 256 bytes, o destinatário receberá os 256 bytes ou não receberá nenhum.
Comparando TCP e UDP
Agora que temos o conceitos dos dois, como vamos escolher o nosso protocolo de transporte? Vamos realizar as comparações:
TCP | UDP | |
Conexão | É baseado em conexão. | Não existe conceito de conexão. Geralmente o mesmo é implementado no nível de aplicativo. |
Confiabilidade | Garante a chegada de todos os pacotes enviados, na ordem em que foram enviados. Também reenvia o pacote se o mesmo for perdido. | Não garante a chegada do mesmo, nem a ordem. A única garantia é que o pacote chegará em 100%. |
Pacotes | Gera os pacotes automaticamente conforme a necessidade. | A criação dos pacotes é implementada na aplicação. |
Escalabilidade | Controla o fluxo de dados automaticamente. | O controle do fluxo é feita pelo aplicativo. |
Escrevendo isso, até parece que o TCP é a melhor coisa que foi inventada. Vamos usar nos jogos, correto? Não exatamente, o TCP facilita muita coisa, entretanto, isso tem um custo de performance muito alto. Quando damos um comando para o TCP enviar o pacote, ele vai criar uma conexão (lembra do processo de handshake do artigo passado?). Em seguida, vai quebrar os dados a serem enviados em pacotes, vai acumular pacotes para que a transmissão seja eficiente, embora este último possa ser desabilitado. Ah! E ainda tem o fator dos pacotes perdidos: se um pacote for perdido, ele é reenviado, e nenhum outro pacote é transmitido até que este seja recebido pelo destinatário.
O fato é que TCP tem um processo muito grande e que fica transparente para o programador. Isso dá a ilusão de que transmissão de dados é algo simples, mas que na realidade custa em desempenho. Ele é bom quando você precisa transferir grandes quantidades de dados de forma contínua, mas em jogos, precisamos de agilidade.
Repense as prioridades
Em um jogo, se considerarmos que 1% dos pacotes são perdidos, essa opção de torna muitas vezes insignificante para jogos. Jogos são dinâmicos e se um pacote atrasar, ele pode ser simplesmente descartado por um mais novo e com informações mais atuais. Ou seja, acabamos de descartar como necessário o fator confiabilidade do TCP. Ele não somente se provou desnecessário, como também se torna inviável para jogos. Na verdade, ficou inviável para qualquer sistema que necessite de transmissão em tempo real, como por exemplo, Skype e serviços de Voip.
Agora você deve estar pensando: e se eu utilizasse UDP para o jogo e o TCP para outras atividades? Um exemplo é carregar um nível do jogo. Será que isso seria uma boa ideia? Afinal, são processos diferentes. Recomendo evitar o uso de UDP e TCP ao mesmo tempo. Quando os dados passam da camada de transporte para a camada de rede, ambos passam para o IP na camada de rede e no fim, um vai interferir no outro. É um assunto mais complicado, portanto deixo para vocês esta leitura complementar chamada “Characteristics of UDP Packet Loss: Effect of TCP Traffic”. Em resumo, o TCP (que pelo que escrevi até agora, passou de herói para vilão) induz perda de pacotes UDP.
Conclusão
Então, pessoal, terminamos de falar sobre a camada de transporte e os seus dois protocolos: TCP e UDP.
Percebemos que para jogos em tempo real, TCP está fora de cogitação. Podem haver casos em que o TCP seja bom? Claro que sim! Por exemplo, onde não é preciso tanta eficiência como em um jogos de turnos, tabuleiros ou que não seja crítico o fator de tempo de resposta. Nesses casos, vamos facilitar o nosso trabalho como desenvolvedor e utilizar o TCP. Portanto, se o fator tempo for algo crítico, como jogos de ação (e que provavelmente é a maior parte), então utilize o UDP.
Até mais!
***
Este artigo foi publicado originalmente em http://www.fabricadejogos.net/posts/desenvolvimento-de-jogos-em-rede-protocolo-udp/