2009-10-28 47 views
8

Necesito poder enviar y recibir paquetes UDP en el mismo puerto. Puedo escuchar, digamos puerto 5000, pero mi envío utiliza un puerto alto aleatorio. El sistema en el que estoy trabajando escrito en VB hace esto y mi necesidad es escribir un respondedor UDP para depurar varios problemas de protocolo.¿Cómo enviar y recibir UDP en el mismo puerto?

estoy usando la biblioteca de código abierto C++ sockets de http://www.alhem.net (Anders Hedstrom) y han sido capaces de utilizar el UdpSocket :: bind() para recibir paquetes UDP entrantes utilizando el UdpSocket función virtual :: OnRawData(), pero tienen No se ha podido provocar que UdpSocket :: Open() (llamadas connect) haga que UdpSocket :: Send() use el puerto elegido en Bind() (en su lugar, usa un puerto random high number).

Mover la función Abrir() no ayuda. He publicado una solicitud en su foro, pero creo, por lo que he leído, que debería ser posible hacerlo, y probablemente no entiendo cómo usar UDP.

¿Alguien tiene alguna idea sobre lo que debo probar?
--gracias--

+0

¿Está llamando a Bind() y Open() en el mismo objeto UdpSocket o dos objetos diferentes? –

+0

Llama a Bind(), y luego a Open(), y luego a Send() utilizando el mismo objeto instanciado. – cedgriss

Respuesta

3

Un enlace de comunicación bidireccional siempre implica dos participantes: un lado del servidor y un lado del cliente.

El cliente espera comunicarse con un servidor en un puerto definido: es por eso que en el lado del servidor uno debe vincular() a un socket.

En el lado del cliente, uno debe abrir un zócalo para el servidor: en realidad no importa qué zócalo se elige (a excepción de la necesidad de que sea gratis).

En otras palabras, no intente especificar un socket en el lado del cliente: la pila del protocolo de red lo asignará a su cliente.

+0

El sistema consiste en una cantidad de nodos que escuchan en el mismo puerto (diferentes direcciones IP). El sistema [A] envía datagrama al sistema [B]. El sistema [B] responde asincrónicamente y envía datagramas a [A] usando el mismo puerto. Incluso si [B] identifica el puerto [A], [A] no está escuchando en ese puerto. Estoy desarrollando un test/respondedor de protocolo para diagnóstico y prueba y tengo que poder aparecer como un subsistema escuchando y enviando desde el mismo puerto #. No puedo cambiar los sistemas existentes que son parte de una implementación estandarizada existente. – cedgriss

+0

¿Puedes dibujar un diagrama? Haría las cosas más simples (al menos para mí). – jldupont

8

sistema consta de un número de nodos que escuchan en mismo puerto (diferente ip addr de). El sistema [A] envía un datagrama al Sistema [B]. El sistema [B] asincrónicamente responde y envía datagramas de vuelta al [A], todos utilizando el mismo puerto. Aunque [B] identifica los puertos [A] 's, [A] no está escuchando en ese puerto

No estoy seguro de entender el 'todo usando el mismo puerto' frase en esa frase. Si A envía un datagrama a B, B conocerá el IP y el puerto de A inmediatamente (una revisión rápida de la documentación de su biblioteca revela que OnRawData tiene un parámetro struct sockaddr *sa, si lo transfiere al sockaddr_in* podrá extraer el par IP: puerto) Puede usar ese IP: puerto para enviar datagramas ay A los recibirá. A no está "escuchando" en ese puerto en el sentido de que no ha llamado a listen() en el socket, sino que A posee un socket que está vinculado a ese puerto (ya sea explícitamente llamando a bind() o al puerto aleatorio asignado por el sistema operativo) recibirá los datos.

Ahora, si desea que TODA su comunicación entre los nodos pase por su puerto fijo, puede hacerlo. Solo tiene que enviar todos sus datagramas a través de su socket de "escucha". Si cada nodo "escucha" en el mismo puerto, significa que cada nodo posee un socket que está vinculado a ese puerto. Si desea que los datagramas enviados de A a B aparezcan desde este puerto fijo, debe enviarlos a través de ese socket. Supongo que es por eso que bind() no funciona para tu socket de envío - A tiene un socket vinculado al puerto X, luego creas otro socket e intentas vincularlo al mismo puerto X, bind() falla ya que el puerto ya está tomado (y no verifica si hay errores :), y luego el sistema operativo asigna un puerto libre aleatorio por encima de 1024.

Nota 1: Uso "escuchar" entre comillas en todas partes, porque el concepto no es muy claro en el contexto de los sockets UDP. Una vez que haya creado el socket y lo haya vinculado a un puerto, ya sea llamando bind() explícitamente o enviando datos y permitiendo que el sistema operativo lo vincule a un puerto, puede recibir datos desde cualquier lugar a través de él. No es necesario escuchar() o aceptar() llamadas.

Nota 2: Usted dice que UdpSocket :: Open() llama a connect(), pero eso no tiene mucho sentido - connect() hace muy poco para sockets UDP - simplemente establece una dirección predeterminada para que pueda usar send() en lugar de sendto() y no especifica la dirección en cada envío.

Espero que aclare las cosas.


Editar para tratar el comentario de OP: Nunca he usado esta biblioteca, pero según sus UdpSocket documentation hay 4 sobrecargas del método Bind() y cada una de ellas acepta el puerto de alguna manera. Ninguno de ellos funciona para ti?

+0

excelente respuesta. – aib

+0

Gracias por su respuesta. Los primeros intentos muestran que sus notas son correctas. Más investigaciones sugieren que debo cambiar el campo sin_port de la estructura de nivel bajo sockaddr * que se pasa a la función de nivel bajo bind() de "0" a mi puerto de origen deseado ("0" significa usar una disponible puerto como src para enviar). Estoy avanzando paso a paso por el código, y todavía no he encontrado la manera de utilizar el objeto UpdSocket de alto nivel para acceder y cambiar esto. Todavía no estoy seguro de que esté bien y espero que la biblioteca tenga una forma de hacerlo. – cedgriss

+0

Redefinido UpdSocket :: Bind() y mientras todos se refieren a la configuración de entrada/recepción, la cuarta versión usa un SocketAddress & struct que también puede tener un puerto de envío. Lo veré con más profundidad y volveré a eso. Gracias de nuevo por la respuesta rápida. – cedgriss

Cuestiones relacionadas