2010-04-11 14 views
6

Estoy escribiendo un servidor UDP, que es el primero para mí; Solo he hecho un poco de comunicaciones TCP. Y estoy teniendo problemas para averiguar exactamente cómo distinguir qué usuario es el que, dado que UDP trata solo con paquetes en lugar de conexiones y, por lo tanto, no puedo decir exactamente con quién me estoy comunicando.¿Cómo se puede distinguir entre dos clientes UDP diferentes en la misma dirección IP?

Aquí es pseudocódigo de mi bucle de servidor actual:

DatagramPacket p; 
socket.receive(p); // now p contains the user's IP and port, and the data 
int key = getKey(p); 
if(key == 0) { // connection request 
    key = makeKey(p); 
    clients.add(key, p.ip); 
    send(p.ip, p.port, key); // give the user his key 
} else { // user has a key 
    // verify key belongs to that IP address 
    // lookup the user's session data based on the key 
    // react to the packet in the context of the session 
} 

En el diseño de este, me quedé en cuenta estos puntos: pueden existir

  • varios usuarios en la misma dirección IP, debido a la presencia de enrutadores, por lo tanto, los usuarios deben tener una clave de identificación por separado.
  • Los paquetes pueden ser falsificados, por lo que la clave debe verificarse con su dirección IP original e ignorarse si un IP diferente intenta usar la clave.
  • El puerto de salida en el lado del cliente puede cambiar entre los paquetes.

¿Es correcta esta tercera suposición o simplemente puedo suponer que una combinación de usuario = un puerto IP +? ¿Se hace esto comúnmente, o debería continuar creando una clave especial como la que estoy haciendo actualmente?

No estoy del todo claro sobre cómo TCP negocia una conexión, así que si crees que debería modelarlo fuera del TCP, por favor, enlázame a un buen tutorial o algo sobre el desastre SYN/SYNACK/ACK de TCP.

También tenga en cuenta que tengo una disposición para volver a enviar una clave, si una IP envía un 0 y esa IP ya tiene una clave pendiente; Lo omití para mantener el fragmento simple. Entiendo que no se garantiza que llegue UDP, y planeo agregar confiabilidad al código de manejo del paquete principal más tarde también.

Respuesta

6

Los encabezados de paquetes UDP tienen un puerto de origen, que generalmente se utiliza como puerto de respuesta. Si no se usa, debe ser cero, y luego corresponde al protocolo de nivel superior determinar cómo coordinar la actividad de solicitud-respuesta con múltiples clientes.

2

Sus preguntas son solo la punta de la lista de problemas de iceburg WRT que debe tener en cuenta al usar UDP. Debería esperar que los enrutadores NAT no proporcionen ningún reenvío significativo de un protocolo UDP que diseñe. El TCP funciona porque los enrutadores entienden el estado de la máquina de estado TCP y de la conexión de almacenamiento de cada sesión para que sepan cómo reenviarlo. Tendrán no idea cómo funciona su protocolo UDP personalizado. Los dispositivos NAT incluyen manejadores de protocolo específicos para aplicaciones UDP bien conocidas.

Si un remitente está vinculado a un puerto de origen o interfaz, los puertos de origen de los remitentes permanecen constantes hasta que se liberan.

Con UDP puede vincular a ambos pares a un puerto de origen conocido para los mensajes salientes (dst) entrantes y (src). Para las aplicaciones cliente/servidor, normalmente desea que el cliente se vincule a un puerto de origen dinámico para que varios clientes puedan coexistir en un solo sistema cliente. El servidor puede responder al cliente utilizando el puerto de origen dinámico proporcionado a través del puerto src desde la solicitud utilizada como puerto de destino en la respuesta. El uso de un puerto conocido para los pares le permite configurar el reenvío UDP en dispositivos NAT.

ex cliente/servidor con servidor en el puerto conocido 3000

cliente se une a un puerto aleatorio (1234), pero sabe que el servidor está escuchando en el puerto 3000. cliente (src 1234) -> servidor (DST 3000) servidor (DST 1234) -> cliente (src 3000) ...

Si un equipo tiene varias interfaces que debe esperar a cualquier necesidad de vincular explícitamente una oyente o remitente a una dirección IP específica o ser capaz de manejar las solicitudes y respuestas de un compañero que se envía y recibe de un IP aleatorio según los caprichos de la tabla de enrutamiento de las computadoras. Si opta por vincular las solicitudes a una interfaz específica, debe conocer la tabla de enrutamiento si los mensajes de un sistema de múltiples domicilios necesitan transitar por una interfaz local diferente para la entrega. Por ejemplo, si enlaza un socket UDP a 127.0.0.1, obviamente no puede usarlo para enviar direcciones IP enrutables de Internet.

En términos de diseño de protocolo, es común enmarcar una sesión ID y campos de secuencia en la carga UDP para que los pares puedan realizar un seguimiento de las sesiones y los intercambios individuales.

Hay una gran cantidad de problemas de fragmentación, coexistencia NAT, seguridad y congestión que debe tener en cuenta para diseñar con éxito un protocolo UDP robusto. Aconsejo contra eso a menos que sea absolutamente necesario.

2
* The outbound port on the client side might change among packets. 

Es eso tercera suposición correcta

No si el cliente sigue usando la misma toma de salida. Enviar el primer datagrama provocará un enlace local, por lo que el socket estará en un puerto local fijo a partir de ese momento.

+0

Así es como funcionan los protocolos UDP típicos. Se espera que un único cliente siga usando el mismo puerto durante una sola "transacción" o "sesión". – caf

+0

Exactamente mi punto. – EJP

Cuestiones relacionadas