Eu sei que o UDP geralmente é recomendado para jogos multiplayer em tempo real com alto uso de dados.
A maioria dos artigos tem vários anos de serviço, e como ~ 80% de todos os dados transmitidos na Internet são TCP, muita otimização deve ter sido feita para o TCP.
Isso me faz pensar: o UDP ainda é superior em termos de velocidade e latência? Otimizações recentes de TCP poderiam ter feito um desempenho melhor do que o UDP?
c++
networking
udp
realtime
KaareZ
fonte
fonte
Respostas:
Não, o UDP ainda é superior em termos de latência de
desempenhoe sempre será mais rápido, devido à filosofia dos 2 protocolos - assumindo que seus dados de comunicação foram projetados com o UDP ou qualquer outra comunicação com perda em mente.O TCP cria uma abstração na qual todos os pacotes de rede chegam e eles chegam na ordem exata em que foram enviados. Para implementar essa abstração em um canal com perdas, ele deve implementar retransmissões e tempos limite, que consomem tempo. Se você enviar 2 atualizações no TCP e um pacote da primeira atualização for perdido, você não verá a segunda atualização até:
Não importa a rapidez com que isso é feito no TCP, porque com o UDP você simplesmente descarta a primeira atualização e usa a segunda, mais nova, agora. Ao contrário do TCP, o UDP não garante que todos os pacotes cheguem e não garante que eles cheguem em ordem.
Isso exige que você envie o tipo certo de dados e projete sua comunicação de forma que a perda de dados seja aceitável.
Se você possui dados em que todos os pacotes devem chegar e os pacotes devem ser processados pelo seu jogo na ordem em que foram enviados, o UDP não será mais rápido. De fato, o uso do UDP nesse caso provavelmente seria mais lento porque você está reconstruindo o TCP e implementando-o por meio do UDP. Nesse caso, você também pode usar o TCP.
EDIT - Adicionando algumas informações adicionais para incorporar / abordar alguns dos comentários:
Normalmente, a taxa de perda de pacotes na Ethernet é muito baixa, mas se torna muito maior quando o WiFi está envolvido ou se o usuário tem um upload / download em andamento. Vamos supor que temos uma perda de pacote perfeitamente uniforme de 0,01% (só ida, não ida e volta). Em um jogo de tiro em primeira pessoa, os clientes devem enviar atualizações sempre que algo acontecer, como quando o cursor do mouse gira o player, o que acontece cerca de 20 vezes por segundo. Eles também podem enviar atualizações por quadro ou em um intervalo fixo, que seria de 60 a 120 atualizações por segundo. Como essas atualizações são enviadas em momentos diferentes, elas devem / devem ser enviadas em um pacote por atualização. Em um jogo de 16 jogadores, todos os 16 jogadores enviam esses 20 a 120 pacotes por segundo ao servidor, resultando em um total de 320 a 1920 pacotes por segundo. Com nossa taxa de perda de pacotes de 0,01%, esperamos perder um pacote a cada 5,2 a 31,25 segundos.
Em todos os pacotes que recebermos após o pacote perdido, enviaremos um DupAck e, após o terceiro DupAck, o remetente retransmitirá o pacote perdido . Portanto, o tempo que o TCP requer para iniciar a retransmissão é de 3 pacotes, mais o tempo que leva para o último DupAck chegar ao remetente. Então precisamos aguardar a retransmissão chegar, portanto, no total, esperamos 3 pacotes + 1 latência de ida e volta. A latência de ida e volta é geralmente de 0 a 1 ms em uma rede local e de 50 a 200 ms na internet. Normalmente, 3 pacotes chegarão em 25 ms se enviarmos 120 pacotes por segundo e em 150 ms se enviarmos 20 pacotes por segundo.
Por outro lado, com o UDP nos recuperamos de um pacote perdido assim que obtemos o próximo pacote, perdemos 8,3 ms se enviarmos 120 pacotes por segundo e 50 ms se enviarmos 20 pacotes por segundo.
Com o TCP, as coisas ficam mais confusas se também precisarmos considerar o Nagle (se o desenvolvedor esquecer de enviar o coalescing ou não puder desativar o ACK atrasado ), evitar o congestionamento da rede ou se a perda de pacotes for ruim o suficiente para sermos responsáveis por vários perdas de pacotes (incluindo perda de Ack e DupAck). Com o UDP, podemos escrever facilmente códigos mais rápidos, porque simplesmente não ligamos para ser um bom cidadão da rede, como o TCP.
fonte
Concordamos que o TCP e o UDP sejam protocolos criados sobre o IP , não é? IP especifica como as mensagens são entregues pela Internet, mas nada diz respeito à estrutura e formato das mensagens. Aí vêm os protocolos TCP e UDP. Eles usam propriedades de IP, mas permitem que o programador se concentre na troca de mensagens sem se preocupar com as camadas inferiores da comunicação na rede. E isso é ótimo, porque lidar com sinais analógicos diretamente nos fios seria meio doloroso.
O TCP fornece um conjunto de funções para enviar e receber mensagens. Ele divide nossos dados em pequenos pacotes para nós mesmos e os envia pela rede. Tudo o que nos pedem é uma porta a ser usada no soquete de rede e a mensagem real que queremos enviar. Além disso, é confiável, o que significa que, se alguns pacotes forem perdidos na rede em que são detectados, serão enviados novamente, enviando-os na mesma ordem em que deveriam chegar.
Por outro lado, o UDP é um protocolo orientado ao controle do usuário. Ao usar o UDP para enviar nossos datagramas , não podemos ter certeza se o datagrama chegará ao destino ou não (e queremos dizer certeza matemática aqui: quando enviamos um pacote, ele provavelmente chegará, mas não podemos ter certeza de que 100%). Além disso, quando um pacote é perdido, ele não será detectado nem enviado novamente.
Nesse ponto, o TCP pareceria a solução ideal para todos os nossos problemas. É confiável, rápido, resolve a latência de conexão para nós, acompanhando quais pacotes chegaram e quais ainda precisamos enviar.
MAS , olhe além. A única vantagem que o UDP nos dá é sua velocidade, e é exatamente isso que realmente queremos. Um pacote UDP é apenas criado, verificado e enviado sem nenhum controle específico, porque é assim que o protocolo UDP funciona. Um pacote TCP deve ser criado, rotulado, verificado e quando chega um ACK é enviado de volta para informar ao remetente "o pacote x está aqui, continue" e, quando esse sinal não é enviado, isso significa que esse pacote x deve ser enviado novamente.
Sim, mas não somente. O UDP é amplamente preferido em relação ao TCP, principalmente porque sua alta velocidade é ideal para lidar com o alto envio e gerenciamento de dados. Isso acontece quando, supondo que esse jogo seja executado em uma etapa determinista (o que acontece no servidor é replicado de forma idêntica em qualquer cliente independentemente da latência da rede), um pacote de atualização é perdido e nunca chega ao seu destino. O TCP reenviou esse pacote e os pacotes a seguir são descartados porque não estão em ordem e são reenviados após o perdido. O UDP é muito mais tolerante nesse cenário: ele não se importará com esse pacote, porque as atualizações mais recentes estão chegando. A atualização perdida não é renderizada; a física do jogo é interpolada com o método de integração usado e a atualização mais recente recebida.
O TCP causa tremulação quando a latência é alta o suficiente, o UDP não:
Bem, sim, é e será por muito tempo. Você pode ler mais sobre TCP vs UDP aqui .
fonte
TCP <- Protocolo de controle de transmissão . É feito para controlar a transmissão.
O TCP foi criado para ser um cidadão de rede bom e diplomático. Ele se concentra em tornar a rede uma boa experiência para todos e, de bom grado, diminui sua produtividade para alcançá-la. Ele se ajusta ao ambiente adicionando latência . Os motivos são, por exemplo:
Além disso
Apesar disso, o TCP fornece o valor mais alto para (dados transmitidos gerais) / (tempo consumido geral). Só que isso não acontece exatamente quando você quer que isso aconteça.
O UDP não faz nada disso. Dispara com a sua vontade, apenas que não se pode esperar que acerte a cada vez - e o alvo deve anunciar que "você não dispara há muito tempo, por quê?". Ainda é possível criar pacotes ACK personalizados, colocar vários registros em um único pacote, etc. E também importante, controlar o percurso da NAT. O UDP certamente é adequado para jogos com baixa demanda de latência.
fonte
Você pode comparar o primeiro diagrama da RFC 768 (UDP) com o primeiro diagrama da página 15 da RFCP 793 (TCP) .
Ambos mostram 16 bits para uma "porta de origem", seguidos por 16 bits para uma "porta de destino". Ambos mostram 16 bits para uma "soma de verificação". De acordo com a RFC 768, o “procedimento de soma de verificação do UDP é o mesmo usado no TCP”.
Enquanto o Comprimento do UDP envolve os detalhes do diagrama do UDP, o comprimento do TCP faz parte de um “pseudo cabeçalho de 96 bits” descrito nas páginas 15 e 16.
Não espere que o TCP supere o UDP. Simplesmente não é provável que isso aconteça, por várias razões. Uma é que o TCP simplesmente possui mais bits. Portanto, se o equipamento puder processar efetivamente um certo número de bits por segundo, isso permitirá mais pacotes UDP do que pacotes TCP.
A outra razão é que o “handshake de três vias” do TCP significa que o remetente deve aguardar uma resposta. Esse requisito introduz uma sobrecarga adicional que o UDP não trata. Há uma razão pela qual a maioria das suas comunicações na Internet começa com alguma comunicação UDP. O DNS básico usa o UDP porque uma solicitação e uma resposta podem ser concluídas em menos etapas do que o processo de "handshake de três vias" do TCP. O recurso do TCP de rastrear pacotes perdidos é bastante desinteressante, porque um computador pode simplesmente fazer uma nova solicitação em vez de tentar informar um sistema remoto que existe uma solicitação anterior não atendida.
fonte
Considere o que está acontecendo por um momento. Para simplificar os cenários, você tem duas opções ao tentar enviar uma mudança de estado (como seu jogador acabou de mudar de direção, ou disparou uma arma, ou outro jogador acabou de disparar uma bomba):
Supondo que não houvesse uma atualização necessária logo antes, o momento em que essa atualização singular chegaria em 1 x 2 não será muito diferente. É uma viagem do servidor para o cliente. Mas, digamos, em vez de apenas uma bomba explodir, você está tentando transmitir continuamente a atividade de alguém correndo por um labirinto; tecelagem, agachamento, tiro, etc. No caso do UDP, todas as ações serão enviadas em um datagrama, assim que acontecer. No caso do TCP, todas as ações serão enviadas em um pacote apenas se o servidor tiver permissão para enviar. O que diz que é permitido enviar? Ter espaço na janela TCP (assumindo que a confirmação de atraso está ativa) para que a mensagem possa ser colocada no fio. Caso contrário, ele precisará aguardar uma confirmação do cliente antes de enviá-lo.
Quanto tempo é muito longo? Quando o desenvolvimento de jogos de tiro em primeira pessoa para vários jogadores atingiu o seu nível, no final dos anos 90 e no início dos anos 2000, as conexões de baixa latência não eram comuns. Um modem dial-up teria uma latência unidirecional típica de 180ms. Esperar por uma confirmação antes de enviar outra atualização, dobrando efetivamente esse tempo para 360ms, foi doloroso; até usuários iniciantes podem definitivamente sentir a diferença. Quando as conexões de banda larga pegaram, diminuíram muito a latência, mas ela ainda persistia quando a largura de banda era escassa (geralmente em algumas áreas). Portanto, a preferência pela menor latência possível persistiu.
As modernas conexões e interconexões domésticas mudaram isso, a ponto de a latência regional, mesmo em horários congestionados do dia, estar na faixa de 15ms ou abaixo. Escolher TCP em vez de UDP seria invisível na maioria dos casos, pois a latência é "baixa o suficiente". No entanto, ainda existe a tendência de o UDP ser priorizado em relação ao TCP, devido ao seu histórico como um protocolo de baixa latência. Portanto, por enquanto (e provavelmente em algum momento no futuro) o UDP será preferido para a comunicação em tempo real.
fonte
Suas suposições estão erradas. O TCP e o UDP diferem principalmente em qual modelo eles representam (datagramas não confiáveis versus fluxo virtual confiável em ordem).
Eles não diferem em relação ao volume ("alto uso de dados") ou taxa de transferência. O TCP enviará tantos dados quanto o UDP, saturando facilmente o cabo físico.
Na presença de perda de pacotes, os dois diferem na latência, mas apenas nessa condição. Caso contrário, o TCP tem latência tão baixa quanto o UDP (mais ou menos algumas dezenas de nanossegundos porque a pilha de rede tem um pouco mais de lógica para fazer, mas isso é bastante negligenciável).
Há uma pequena diferença no tamanho do cabeçalho; portanto, tecnicamente, mais bytes precisam passar por fios nas linhas seriais, mas esse também é um tanto inconseqüente. Isso realmente importa apenas para transferências em massa e, portanto, é uma diferença de 0,5%. A maioria das pessoas com acesso doméstico à Internet DSL direciona todo o tráfego por ATM, o que aumenta em mais de 10% a sobrecarga do protocolo (5 bytes de controle para 48 bytes de carga útil, mais quadros parciais), e ninguém percebe.
Algumas pessoas criam confiabilidade sobre o UDP. Se for desejado algum nível de confiabilidade, mas não for necessária uma entrega estrita em ordem, isso pode dar uma pequena vantagem. No entanto, ainda é discutível se a abordagem faz muito sentido e você paga um preço alto por essa pequena vantagem.
Se você tiver clientes conectados a partir de hotéis WiFis ou outros locais "estranhos", notará que geralmente o suporte geral ao TCP é muito, muito melhor que o UDP.
Os jogos geralmente usam o UDP não porque é superior em uma das formas mencionadas acima - não é - ou porque você pode reduzir a instabilidade em meio milissegundo implementando a confiabilidade sem ordem, mas porque os jogos (como a telefonia IP) geralmente contêm muitos dados muito voláteis, como, por exemplo, atualizações de posição.
Esses dados voláteis são obsoletos com rapidez e regularidade, com o passar do tempo e com o próximo datagrama chegando. O que significa nada mais e nada menos do que você realmente não se importa muito em ser 100% confiável (ou em ordem).
Supondo que um pacote de rede seja descartado em um serviço que é executado em um ritmo constante com atualizações frequentes chegando (jogo de tiro, telefone, bate-papo por vídeo), não faz muito sentido ter o tempo limite de reconhecimento e reenviar o pacote e, enquanto isso congele tudo do outro lado enquanto aguarda a chegada do pacote reenviado. Isso é muito perturbador e não é bom.
Em vez disso, basta considerar o pacote perdido e seguir em frente, levando os dados do próximo pacote que o compõe e, enquanto isso, o melhor possível, ocultar o fato de que um pacote foi perdido do usuário. Interpolação, acerto de contas morto, você escolhe.
Observe pela maneira como a perda de pacotes é uma condição normal. Embora o IP seja geralmente "bastante confiável", os pacotes que são descartados ocasionalmente podem acontecer e acontecerão . Enquanto os pacotes perdidos são normalmente bastante raros (<1% aqui), não é algo extraordinário ou teórico, ou uma indicação de que algo está quebrado. É perfeitamente normal.
Toda transferência em massa TCP necessariamente inclui pacotes perdidos, por exemplo (é assim que o controle de congestionamento funciona).
fonte
Em um MPG de alta largura de banda, você não se importa se perdeu um pacote, fornecendo a localização e a saúde do monstro # 425, porque estará recebendo outra atualização em uma fração de segundo. Este é um exemplo em que o UDP faz com que o TCP pareça estúpido por fazer você esperar por dados obsoletos instantaneamente.
Nesse mesmo jogo, você deseja que os patches apareçam exatamente como foram projetados. O TCP já possui os recursos "diga-me se falhar", facilitando novas tentativas automáticas e falhas verificadas. Você pode fazer isso no UDP, mas por que recriar a tecnologia?
Aqui está uma descrição simples do que está acontecendo.
UDP - Isolar o pedaço O'data.
Faça um pacote.
Encapsular em IP.
Enviá-lo.
TCP - isole um fluxo de dados.
Faça um pacote da frente do fluxo.
Encapsular em IP.
Aguarde espaço na janela TCP.
Enviá-lo.
Mantenha a remessa até que um recibo seja recebido ou exceda o tempo limite.
Permaneça na janela TCP até que um recibo seja recebido ou o tempo limite.
O envio significa apenas que ele passou pela NIC local, não mais.
Uma recepção de recibo TCP garante a recepção de dados e libera espaço na janela para o próximo pacote.
Reenviar (ligeiramente) aumenta a probabilidade de recebimento eventual.
Pacotes TCP são remontados do outro lado como um fluxo ordenado de dados. Pacotes UPD são recebidos como pacotes distintos. O protocolo não preserva a ordem.
O TCP é bom para enviar dados necessários e grandes quantidades ordenadas de dados. O TCP fornece notificação de uma falha persistente. O TCP se auto-acelera através de tubos bloqueados (ref: window). O TCP possui handshakes para diminuir a inicialização. O TCP requer uma "conexão" antes da transmissão.
O UDP apenas coloca os dados em conexão e permite prosseguir sem esperar janelas e retransmissões. O UDP enviará os dados a toda velocidade para um tubo obstruído, independentemente da quantidade de dados perdidos.
Projetei e escrevi um UDP Multicast File Transport Utility aplicado comercialmente. Eu trabalhei em pilhas de IP. Isso é apenas básico, sem minúcia. Explicar "soquetes, MTUs e outros brinquedos divertidos" foi um pouco além do que seria útil para essa pergunta.
Ps (não consigo adicionar comentários para responder aos comentários) O UDP também é bom para dados desejáveis, mas não necessários. A Correção de erro de encaminhamento é um exemplo disso, muitos pacotes desnecessários, mas desejáveis.
fonte
Mais uma pergunta é: "dados pesados" significam que você frequentemente carrega cenas?
Se sim, pode ser necessário enviar grandes quantidades de dados (> 1k) intensivamente, nos quais o TCP pode ser muito mais eficiente, porque especialmente no lado do servidor, as NICs fornecerão várias descargas no mesmo lote de ciclos. Um aplicativo de espaço do usuário pode emitir gravações grandes com TCP enquanto estiver no UDP, uma tentativa de enviar mais do que bytes de tamanho de cabeçalho MTU causará fragmentação de IP e outras sobrecargas que prejudicarão o desempenho
fonte
Nem o UDP ou o TCP (ou qualquer outra variante) são superiores , nem mesmo em termos de velocidade / latência. Sua escolha deve ser feita dependendo dos requisitos do seu aplicativo. Para fazer isso, você deve comparar os recursos que cada protocolo oferece, percebendo que mais recursos implicam mais sobrecarga. Portanto, se o objetivo é minimizar a latência ou maximizar a velocidade, você deve escolher um protocolo com o mínimo de recursos possível, mas mantendo os recursos essenciais necessários para atender aos seus requisitos.
Uma comparação de protocolos
De um modo geral, o UDP (User Datagram Protocol) oferece a menor quantidade de recursos. É simplista o fato de você enviar dados sem qualquer tipo de recebimento / reconhecimento.
Por outro lado, o TCP (Transmission Control Protocol) oferece a maior quantidade de recursos necessários para uma comunicação conectada e confiável. Uma comunicação TCP envia duplicados ou mais de pacotes e os marca com informações sobre pedidos. Após o recebimento no destino, um ACK (reconhecimento) deve ser enviado de volta, juntamente com as informações sobre quais pacotes foram perdidos, para que o remetente original possa reenviar esses pacotes perdidos. Se bem me lembro, até os pacotes ACK podem precisar de reconhecimento pela confiabilidade adequada.
Exemplo: chamada em conferência do Skype
Para uma teleconferência do Skype, não é importante garantir que todos os dados de vídeo e áudio sejam enviados / recebidos de maneira confiável. Atualmente, o UDP faz um excelente trabalho ao minimizar a perda de pacotes. O importante é saber que não há absolutamente nenhuma garantia no UDP se a transmissão foi ou não bem-sucedida. Para dados de áudio / vídeo em uma teleconferência, o UDP é uma escolha adequada, porque nos preocupamos mais em obter dados em tempo real (ou seja, os mais recentes). Se alguns pacotes forem perdidos aqui e ali, isso não interromperá a comunicação de maneira dramática.
No entanto, em uma chamada em conferência, as pessoas podem enviar mensagens instantâneas (mensagens instantâneas) ou arquivos. Nesses casos, a confiabilidade é um requisito necessário para garantir que arquivos e mensagens não sejam corrompidos ou perdidos. Para mensagens instantâneas, talvez você não precise do estado conectado que o TCP fornece. Um protocolo intermediário, como o RUDP (UDP confiável), pode ser suficiente. No entanto, para arquivos, pode ser necessário ter o estado conectado que o TCP fornece.
Opções de implementação
Se você tem um aplicativo complexo ou precisa otimizar sua comunicação, é benéfico começar com uma comunicação UDP. Depois, você pode adicionar todos os recursos necessários na parte superior. Isso lhe dará o máximo controle sobre sua comunicação em rede.
Se você tiver um aplicativo simples onde a otimização não é necessária, considere optar por um padrão (UDP ou TCP) para atender às suas necessidades. Isso permitiria que você passasse para assuntos mais importantes.
fonte
Notei muitos comentários em que as pessoas acreditam que os pacotes TCP são maiores que os pacotes UDP. Não confie apenas em mim, leia a documentação. O protocolo é o seguinte: alguns bytes para o cabeçalho Ethernet (tipo de mensagem de 2 bytes, MAC de 48 bits, 6 bytes) (para Wifi, o cabeçalho pode ser diferente) 20 bytes para IP 20 bytes para TCP ou UDP x bytes para os dados x variação de 0 a cerca de 1500 (consulte MTU) Por fim, a soma de verificação para garantir que não ocorram danos nesse pacote Ethernet.
O TCP permite enviar pacotes "stream" maiores de cerca de 64K. Este bloco "grande" é realmente dividido em muitos pacotes Ethernet menores.
fonte