Sé que UDP generalmente se recomienda para juegos multijugador en tiempo real con alto uso de datos.
La mayoría de los artículos tienen años de servicio, y dado que ~ 80% de todos los datos transmitidos en Internet son TCP, se debe haber hecho mucha optimización para TCP.
Esto me hace preguntarme: ¿UDP sigue siendo superior en términos de velocidad y latencia? ¿Podrían las optimizaciones TCP recientes haber hecho que TCP funcione mejor que UDP?
c++
networking
udp
realtime
KaareZ
fuente
fuente
Respuestas:
No, UDP sigue siendo superior en términos de latencia de
rendimientoy siempre será más rápido, debido a la filosofía de los 2 protocolos: suponiendo que sus datos de comunicación se diseñaron teniendo en cuenta UDP o cualquier otra comunicación con pérdida.TCP crea una abstracción en la que llegan todos los paquetes de red, y llegan en el orden exacto en que fueron enviados. Para implementar tal abstracción en un canal con pérdida, debe implementar retransmisiones y tiempos de espera, que consumen tiempo. Si envía 2 actualizaciones en TCP y se pierde un paquete de la primera actualización, no verá la segunda actualización hasta que:
No importa qué tan rápido se haga esto en TCP, porque con UDP simplemente descartas la primera actualización y usas la segunda, más nueva, en este momento. A diferencia de TCP, UDP no garantiza que lleguen todos los paquetes y tampoco garantiza que lleguen en orden.
Esto requiere que envíe el tipo correcto de datos y diseñe su comunicación de tal manera que sea aceptable perder datos.
Si tiene datos a donde debe llegar cada paquete, y su paquete debe procesarlos en el orden en que fueron enviados, entonces UDP no será más rápido. De hecho, usar UDP en este caso probablemente sea más lento porque está reconstruyendo TCP e implementándolo por medio de UDP, en cuyo caso también podría usar TCP.
EDITAR: agregar información adicional para incorporar / abordar algunos de los comentarios:
Normalmente, la tasa de pérdida de paquetes en Ethernet es muy baja, pero se vuelve mucho más alta una vez que WiFi está involucrado o si el usuario tiene una carga / descarga en progreso. Supongamos que tenemos una pérdida de paquetes perfectamente uniforme de 0.01% (unidireccional, no ida y vuelta). En un juego de disparos en primera persona, los clientes deben enviar actualizaciones cada vez que sucede algo, como cuando el cursor del mouse gira el reproductor, lo que ocurre aproximadamente 20 veces por segundo. También podrían enviar actualizaciones por cuadro o en un intervalo fijo, que serían 60-120 actualizaciones por segundo. Como estas actualizaciones se envían en diferentes momentos, se enviarán / deberían enviarse en un paquete por actualización. En un juego de 16 jugadores, los 16 jugadores envían estos 20-120 paquetes por segundo al servidor, lo que da como resultado un total de 320-1920 paquetes por segundo. Con nuestra tasa de pérdida de paquetes de 0.01%, esperamos perder un paquete cada 5.2-31.25 segundos.
En cada paquete que recibamos después del paquete perdido, enviaremos un DupAck, y después del tercer DupAck, el remitente retransmitirá el paquete perdido . Por lo tanto, el tiempo que TCP requiere para iniciar la retransmisión es de 3 paquetes, más el tiempo que tarda el último DupAck en llegar al remitente. Luego, debemos esperar a que llegue la retransmisión, por lo que en total esperamos 3 paquetes + 1 latencia de ida y vuelta. La latencia de ida y vuelta suele ser de 0-1 ms en una red local y de 50-200 ms en Internet. 3 paquetes llegarán típicamente en 25 ms si enviamos 120 paquetes por segundo, y en 150 ms si enviamos 20 paquetes por segundo.
En contraste, con UDP nos recuperamos de un paquete perdido tan pronto como recibimos el siguiente paquete, por lo que perdemos 8,3 ms si enviamos 120 paquetes por segundo y 50 ms si enviamos 20 paquetes por segundo.
Con TCP, las cosas se vuelven más complicadas si también tenemos que considerar Nagle (si el desarrollador olvida desactivar la fusión de envíos o no puede deshabilitar el ACK retrasado ), evitar la congestión de la red o si la pérdida de paquetes es lo suficientemente mala como para tener que dar cuenta de múltiples pérdidas de paquetes (incluidas las pérdidas Ack y DupAck). Con UDP podemos escribir fácilmente un código más rápido porque simplemente no nos importa ser un buen ciudadano de la red como lo hace TCP.
fuente
Estamos de acuerdo en que tanto TCP como UDP son protocolos construidos sobre IP , ¿no? IP especifica cómo se entregan los mensajes a través de Internet, pero nada se trata de la estructura y el formato de los mensajes. Aquí vienen los protocolos TCP y UDP. Utilizan las propiedades de IP, pero permiten que el programador se concentre en el intercambio de mensajes sin preocuparse por las capas más bajas de la comunicación de red. Y eso es genial, porque tratar con señales analógicas en cables directamente sería un poco doloroso.
TCP proporciona un conjunto de funciones para enviar y recibir mensajes. Divide nuestros datos en pequeños paquetes para nosotros y los enviamos a través de la red. Todo lo que se nos pide es un puerto para usar para el socket de red y el mensaje real que queremos enviar. Además, es confiable, lo que significa que si algunos paquetes se pierden a lo largo de la red que se detectan, luego se envían nuevamente con el cuidado de enviarlos en el mismo orden en que se suponía que llegarían.
Por otro lado, UDP es un protocolo orientado hacia el control del usuario. Cuando usamos UDP para enviar nuestros datagramas , no podemos estar seguros de si el datagrama llegará alguna vez a destino o no (y queremos decir certeza matemática aquí: cuando enviamos un paquete probablemente llegará, pero no podemos estar seguros de 100%) Además, cuando se pierde un paquete, no se detectará ni se volverá a enviar.
En este punto, TCP sería la solución ideal para todos nuestros problemas. Es confiable, es rápido, resuelve la latencia de conexión para nosotros al realizar un seguimiento de qué paquetes llegaron y qué paquetes aún tenemos que enviar.
PERO , mira más allá. La única ventaja que nos brinda UDP es su velocidad, y eso es lo que realmente queremos. Un paquete UDP se crea, se envía y se envía sin ningún control en particular, porque así es como funciona el protocolo UDP. Un paquete TCP debe ser diseñado, etiquetado, marcado, y cuando llegue, se enviará un ACK para decirle al remitente "el paquete x está aquí, continúe" , y cuando esta señal no se envía, eso significa que dicho paquete x debe enviarse de nuevo.
Sí, pero no solo UDP es ampliamente preferido sobre TCP principalmente porque su alta velocidad es idea para manejar el envío y la gestión de datos de alta. Esto sucede cuando, suponiendo que dicho videojuego se ejecute en un bloqueo determinista (lo que sucede en el servidor se replica idénticamente en cualquier cliente independientemente de la latencia de la red), se pierde un paquete de actualización y nunca llega a su destino. TCP volvería a enviar dicho paquete, y los siguientes paquetes se descartan porque no llegan en orden, y luego se vuelven a enviar después del perdido. UDP es mucho más tolerante en este escenario: no le importará este paquete, porque las actualizaciones más recientes están por llegar. La actualización perdida no se procesa, sino que la física del juego se interpola según el método de integración utilizado y la última actualización recibida.
TCP provoca fluctuaciones cuando la latencia es lo suficientemente alta, UDP no:
Bueno, sí, lo es y lo hará por mucho tiempo. Puede leer más sobre TCP vs UDP aquí .
fuente
TCP <- Protocolo de control de transmisión . Está hecho para controlar la transmisión.
TCP fue creado para ser un buen ciudadano de la red diplomática. Se centra en hacer que la creación de redes sea una buena experiencia para todos, y voluntariamente disminuye su rendimiento para lograrlo. Se ajusta al entorno agregando latencia . Las razones son, por ejemplo:
Adicionalmente
A pesar de esto, TCP proporciona la cifra más alta para (datos transmitidos en general) / (tiempo total consumido). Solo que no sucede precisamente cuando quieres que suceda.
UDP no hace nada de esto. Se dispara a su voluntad, solo que uno no puede esperar que golpee cada vez; en lugar de eso, el objetivo debe anunciar que "no ha disparado en mucho tiempo, ¿por qué?". Todavía se pueden crear paquetes ACK personalizados, colocar múltiples registros en un solo paquete, etc. Y también es importante, controlar el recorrido NAT. UDP es sin duda adecuado para juegos con baja demanda de latencia.
fuente
Puede comparar el primer diagrama de RFC 768 (UDP) con el primer diagrama de RFCP 793 (TCP) página 15 .
Ambos muestran 16 bits para un "puerto de origen" seguido de 16 bits para un "puerto de destino". Ambos muestran 16 bits para una "suma de verificación". Según RFC 768, el "procedimiento de suma de verificación de UDP es el mismo que se utiliza en TCP".
Mientras que la longitud de UDP envuelve los detalles del diagrama de UDP, la longitud de TCP es parte de un "pseudo encabezado de 96 bits" descrito en las páginas 15 y 16.
No espere que TCP supere a UDP. Eso simplemente no es probable que ocurra, por múltiples razones. Una es que TCP simplemente tiene más bits. Entonces, si el equipo puede procesar efectivamente un cierto número de bits por segundo, eso permitirá más paquetes UDP que paquetes TCP.
La otra razón es que el "protocolo de enlace de tres vías" de TCP significa que el remitente debe esperar una respuesta. Este requisito introduce una sobrecarga adicional que UDP no maneja. Hay una razón por la cual la mayoría de sus comunicaciones por Internet comienzan con alguna comunicación UDP. El DNS básico utiliza UDP porque una solicitud y una respuesta se pueden completar en menos pasos que el proceso de "protocolo de enlace de tres vías" de TCP. La característica de TCP de realizar un seguimiento de los paquetes perdidos es bastante poco emocionante, porque una computadora podría simplemente hacer una nueva solicitud en lugar de tratar de informar a un sistema remoto que hay una solicitud previa no cumplida.
fuente
Considera lo que sucede por un momento. Para simplificar los escenarios, tienes dos opciones cuando intentas enviar un cambio de estado (como que tu jugador acaba de cambiar de dirección, o disparó un arma, o algún otro jugador simplemente lanzó una bomba):
Suponiendo que no se necesitaba una actualización justo antes, el momento en que llegue esa actualización singular en 1 vs 2 no será muy diferente. Es un viaje del servidor al cliente. Pero, digamos que en lugar de que solo explote una bomba, está tratando de transmitir continuamente la actividad de alguien corriendo por un laberinto; tejido, agacharse, disparar, etc. En el caso de UDP, cada acción se enviará en un datagrama, tan pronto como suceda. En el caso de TCP, cada acción se enviará en un paquete solo si el servidor puede enviar. ¿Qué dice que está permitido enviar? Tener espacio en la ventana TCP (suponiendo que el reconocimiento retrasado esté activo) para que el mensaje se pueda colocar en el cable. Si no, tiene que esperar a que llegue un reconocimiento del cliente antes de enviarlo.
¿Cuánto tiempo es demasiado largo? Cuando el desarrollo del juego de disparos en primera persona multijugador llegó a su final a finales de los 90 y principios de los 2000, las conexiones de baja latencia no eran comunes. Un módem de acceso telefónico tendría una latencia unidireccional típica de 180 ms. Esperar un momento antes de enviar otra actualización, duplicando efectivamente ese tiempo a 360 ms, fue doloroso; incluso los usuarios novatos definitivamente podrían sentir la diferencia. Cuando las conexiones de banda ancha se pusieron de moda, redujeron mucho la latencia, pero persistió cuando el ancho de banda era escaso (con frecuencia en algunas áreas). Por lo tanto, la preferencia por la latencia más baja posible persistió.
Las conexiones e interconexiones hogareñas modernas han cambiado esto, hasta el punto en que la latencia regional, incluso durante los momentos congestionados del día, está en el rango de 15 ms o menos. Elegir TCP en lugar de UDP sería invisible en la mayoría de los casos, ya que la latencia es "lo suficientemente baja". Sin embargo, todavía existe la tendencia de que UDP tenga prioridad sobre TCP dado su historial como un protocolo de baja latencia. Entonces, por ahora (y probablemente en algún momento en el futuro) UDP será preferido para la comunicación en tiempo real.
fuente
Tus suposiciones están equivocadas. TCP y UDP difieren principalmente en qué modelo representan (datagramas poco confiables versus flujo virtual confiable en orden).
No difieren con respecto al volumen ("alto uso de datos") o el rendimiento. TCP empujará tantos datos como UDP, saturará fácilmente el cable físico.
En presencia de pérdida de paquetes, los dos difieren en latencia, pero solo en esa condición. De lo contrario, TCP tiene una latencia tan baja como UDP (más o menos unas pocas docenas de nanosegundos porque la pila de red tiene un poco más de lógica que hacer, pero eso es bastante despreciable).
Hay una ligera diferencia en el tamaño del encabezado, por lo que técnicamente, más bytes deben pasar por el cable en las líneas seriales, pero ese también es bastante intrascendente. Realmente solo importa para transferencias masivas, y luego se trata de una diferencia de 0.5%. La mayoría de las personas con acceso a Internet DSL en el hogar enrutan todo su tráfico a través de ATM, lo que agrega más del 10% de sobrecarga de protocolo (5 bytes de control para 48 bytes de carga útil, más tramas parciales), y nadie se da cuenta.
Algunas personas construyen confiabilidad sobre UDP. Si se desea cierto nivel de confiabilidad, pero no se necesita una entrega estricta en orden, eso puede dar una pequeña ventaja. Sin embargo, todavía es discutible si el enfoque tiene mucho sentido y si paga un precio considerable por esa pequeña ventaja.
Si tiene clientes que se conectan desde WiFis del hotel u otros lugares "extraños", notará que a menudo el soporte general para TCP es mucho, mucho mejor que para UDP.
Los juegos generalmente usan UDP no porque sea superior en una de las formas mencionadas, no lo es, o porque puede reducir la fluctuación de fase en medio milisegundo implementando confiabilidad sin orden, sino porque los juegos (al igual que la telefonía IP) a menudo contienen muchos datos muy volátiles, como por ejemplo actualizaciones de posición.
Estos datos volátiles son obsoletos de manera regular y rápida tanto por el paso del tiempo como por el próximo datagrama que ingresa. Lo que significa nada más y nada menos que realmente no te importa demasiado ser 100% confiable (o en orden).
Suponiendo que un paquete de red se descarta en un servicio que se ejecuta a un ritmo constante con actualizaciones frecuentes (juego de disparos, teléfono, video chat), no tiene mucho sentido tener el tiempo de confirmación y reenviar el paquete, y mientras tanto congele todo en el otro extremo mientras espera que llegue el paquete reenviado. Eso es demasiado inquietante, y no es bueno.
En cambio, solo considera el paquete perdido y sigue adelante, tomando los datos del siguiente paquete que lo atraviesa y, mientras tanto, lo mejor que pueda, oculta el hecho de que el usuario perdió un paquete. Interpolación, cálculo muerto, lo que sea.
Tenga en cuenta que la pérdida de paquetes es una condición normal. Si bien la IP es generalmente "bastante confiable", los paquetes que se descartan ocasionalmente pueden suceder y sucederán . Si bien los paquetes que se pierden normalmente son más bien raros (<1% aquí), no es algo extraordinario o teórico, o una indicación de que algo está roto. Es perfectamente normal.
Cada transferencia masiva TCP necesariamente incluirá paquetes perdidos, por ejemplo (así es como funciona el control de congestión).
fuente
En un MPG de ancho de banda alto, no te importa si te perdiste un paquete que te da la ubicación y el estado del monstruo # 425, porque recibirás otra actualización en una fracción de segundo. Este es un ejemplo en el que UDP hace que TCP parezca estúpido por hacer que espere datos instantáneamente obsoletos.
En ese mismo juego, quieres que los parches se muestren exactamente como fueron diseñados. TCP ya tiene incorporadas las funciones "dime si falla", lo que facilita los reintentos automáticos y las fallas verificadas. Puedes hacerlo en UDP, pero ¿por qué recrear la tecnología?
Aquí hay una descripción simple de lo que está sucediendo.
UDP: aislar el fragmento O'data.
Haz un paquete
Encapsular en IP.
Envíalo.
TCP: aísla un flujo de datos.
Haga un paquete desde el frente de la secuencia.
Encapsular en IP.
Espere espacio en la ventana TCP.
Envíalo.
Siga reenviando hasta que se reciba un recibo o se agote el tiempo de espera.
Permanezca en la ventana TCP hasta que se reciba un recibo o se agote el tiempo de espera.
El envío solo significa que lo hizo a través de la NIC local, no más.
Una recepción de recibo TCP garantiza la recepción de datos y libera espacio en la ventana para el siguiente paquete.
Reenviar (ligeramente) aumenta la probabilidad de un eventual recibo.
Los paquetes TCP se vuelven a ensamblar en el otro lado como una secuencia ordenada de datos. Los paquetes UPD se reciben como paquetes distintos. El protocolo no conserva el orden.
TCP es bueno para enviar datos requeridos y grandes cantidades ordenadas de datos. TCP proporciona notificación de una falla persistente. TCP se auto-acelera a través de tuberías estranguladas (ref: ventana). TCP tiene apretones de manos para ralentizar la inicialización. TCP requiere una "conexión" antes de la transmisión.
UDP solo pone los datos en el cable y le permite continuar sin esperar ventanas y retransmisiones. UDP enviará datos a toda velocidad a una tubería obstruida, sin importar cuántos datos se pierdan.
Diseñé y escribí una utilidad de transporte de archivos UDP multicast aplicada comercialmente. He trabajado en pilas de IP. Estos son solo conceptos básicos, sin minucias. Explicar "enchufes, MTU y otros juguetes divertidos" fue un poco más allá de lo que sería útil para esta pregunta.
Ps (no puedo agregar comentarios para responder a los comentarios) UDP también es bueno para los datos que son deseables pero no necesarios. La corrección de errores de reenvío es un ejemplo de esto, muchos paquetes innecesarios pero deseables.
fuente
Una pregunta más es: ¿significa "datos pesados" que cargará escenas con frecuencia?
En caso afirmativo, es posible que deba enviar grandes cantidades de datos (> 1k) de manera intensiva, en los que TCP puede ser mucho más eficiente porque, especialmente en el lado del servidor, las NIC proporcionarán varias descargas en el mismo lote de ciclos. Una aplicación de espacio de usuario puede emitir grandes escrituras con TCP mientras que en UDP un intento de enviar más de bytes de tamaño de encabezados MTU causará fragmentación de IP y otros gastos generales que matarán el rendimiento
fuente
Ni UDP ni TCP (ni ninguna otra variante) es superior a la derecha , ni siquiera en términos de velocidad / latencia. Su elección debe hacerse según los requisitos de su aplicación. Para hacer esto, debe comparar las características que ofrece cada protocolo, dándose cuenta de que más características implican más sobrecarga. Por lo tanto, si el objetivo es minimizar la latencia o maximizar la velocidad, debe elegir un protocolo con la menor cantidad de funciones posible, pero manteniendo las funciones esenciales necesarias para cumplir con sus requisitos.
Una comparación de protocolos
En términos generales, UDP (User Datagram Protocol) ofrece la menor cantidad de características. Es simplista porque envía datos sin ningún tipo de recibo / acuse de recibo.
Por otro lado, TCP (Protocolo de Control de Transmisión) ofrece la mayor cantidad de características necesarias para una comunicación confiable y conectada. Una comunicación TCP envía duplicados o más paquetes y los etiqueta con información de pedido. Al recibirlo en el destino, se debe enviar un ACK (acuse de recibo) junto con la información sobre los paquetes que se perdieron para que el remitente original pueda reenviar esos paquetes perdidos. Si recuerdo correctamente, incluso los paquetes ACK pueden necesitar reconocimiento para la confiabilidad adecuada.
Ejemplo: llamada de conferencia de Skype
Para una llamada de conferencia de Skype, no es importante asegurarse de que todos los datos de video y audio se envíen / reciban de manera confiable. Hoy en día, UDP hace un gran trabajo al minimizar la pérdida de paquetes de todos modos. Lo importante es saber que no hay absolutamente ninguna garantía en UDP si la transmisión fue exitosa o no. Para los datos de audio / video en una llamada de conferencia, UDP es una opción adecuada porque nos preocupamos más por obtener datos en tiempo real (es decir, el más reciente). Si se pierden algunos paquetes aquí y allá, no interrumpirá la comunicación de manera dramática.
Sin embargo, en una llamada de conferencia, las personas pueden enviar mensajes instantáneos (IM) o enviar archivos. En estos casos, la confiabilidad es un requisito necesario para garantizar que los archivos y mensajes no se corrompan o pierdan. Para los mensajes instantáneos, es posible que no necesite el estado conectado que proporciona TCP. Un protocolo intermedio, como RUDP (UDP confiable) puede ser suficiente. Sin embargo, para los archivos, puede ser necesario tener el estado conectado que proporciona TCP.
Opciones de implementación
Si tiene una aplicación compleja o necesita optimizar su comunicación, entonces es beneficioso comenzar con una comunicación UDP. Luego, puede agregar todas las funciones que necesita en la parte superior. Esto le dará el mayor control sobre su comunicación de red.
Si tiene una aplicación simple donde no se requiere optimización, considere optar por uno estándar (UDP o TCP) para satisfacer sus necesidades. Eso le permitiría pasar a asuntos más importantes.
fuente
Noté muchos comentarios en los que la gente cree que los paquetes TCP son más grandes que los paquetes UDP. No solo confíes en mí, lee la documentación. El protocolo es el siguiente: unos pocos bytes para el encabezado Ethernet (tipo de mensaje de 2 bytes, MAC de 48 bits, 6 bytes) (para Wifi, el encabezado puede diferir) 20 bytes para IP 20 bytes para TCP o UDP x bytes para el rango de datos x de 0 a aproximadamente 1500 (ver MTU) Por último, la suma de comprobación para asegurarse de que no se produjo corrupción en ese paquete Ethernet.
TCP permite enviar paquetes de "transmisión" más grandes de aproximadamente 64K. Este bloque "grande" en realidad está cortado en muchos paquetes Ethernet más pequeños.
fuente