![]() |
![]() |
![]() |
![]() |
![]() |
FTP | ![]() |
![]() |
CCD | ![]() |
![]() |
Buscar | ![]() |
![]() |
Trucos | ![]() |
![]() |
Trabajo | ![]() |
![]() |
Foros | ![]() |
|
Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Temas de Hoy |
![]() |
|
Herramientas | Buscar en Tema | Desplegado |
#1
|
||||
|
||||
Mensajes Broadcast vía UDP entre varias instancias corriendo en una misma máquina
Cuanto tiempo sin aparecer por aquí !!!
![]() Saludos a todos en primer lugar. Necesito de nuevo una ayudita. Mi aplicación funcionaba perfectamente en red local con varios ordenadores, basándome en comunicaciones con TIdUPDServer y TIdUPDClient para enviar mensajes e información de un puesto a otro. Necesito que sean comunicaciones UDP porque no necesito contestación obligatoria sino que lanzo (Broadcast) mensajes y los demás si lo escuchan, actualizan información que el puesto que envía el broadcast está informando que ha cambiado. Todo eso funcionaba perfectamente hasta que a algunos clientes se les está ocurriendo (para bien) montar la aplicación en servidores virtuales y accediendo con Escritorio Remoto. En este caso, tengo múltiples instancias de mi aplicación corriendo a la vez en la misma máquina, y no puedo abrir el puerto UDP que haya asignado en dos instancias diferentes DENTRO DE LA MISMA MAQUINA. Y ahí es donde empiezan mis problemas de comunicación entre aplicaciones .... Cómo se podría resolver elegantemente, teniendo en cuenta el hecho de que realmente no necesito comunicación TCP, ya que como indicaba, lanzo 'broadcast's' para que los programas que estuvieran activas pudieran tomar una actuación determinada ? Qué otra solución habría que no fuera utilizar los componentes de Indy y basarme en cualquier otra estructura ? Gracias una vez más a todos por vuestros comentarios. Saludos
__________________
Piensa siempre en positivo ! |
#2
|
||||
|
||||
Saludos, tanto tiempo
![]() No conozco la solución a tu duda ![]()
__________________
La otra guía de estilo | Búsquedas avanzadas | Etiquetas para código | Colabora mediante Paypal |
#3
|
||||
|
||||
Hola gluglu,
Te respondo de lo que encontré en internet. Al parecer podrias usar Named Pipes o Sockets Sockets: MultiCast Messages to multiple clients on the same machine Named Pipes: Named Pipes unit for Delphi Cita:
__________________
Buena caza y buen remar... http://mivaler.blogspot.com |
#4
|
||||
|
||||
Cita:
Se supone que cada servidor virtual tiene su propia dirección IP, suponiendo que estemos hablando de vmware esx server o cosas así. Si en una misma maquina hay, por ejemplo, dos conexiones con escritorio remoto, cada una de ellas será a una maquina virtual distinta, con distinta ip, y eso no son instancias diferentes en la misma maquina, sino en distintas, aunque sean virtuales. Por tanto no necesitarías tocar nada de tu aplicación. A no ser que te refieras a otra cosa, claro. Un saludo!
__________________
"la única iglesia que ilumina es la que arde" Anonimo |
#5
|
||||
|
||||
Gracias a todos por vuestras respuestas.
Movorack : Ya había visto todos esos links antes de postear aquí pero no me dan la solución que necesito. Julián : Efectivamente, eso pensaba yo también. Pero no es así. Cuando en una segunda instancia (o sucesivas...) el programa intenta de nuevo abrir el puerto que está configurado, me da error indicando que es puerto ya está en uso. Independientemente de que fuera un servidor virtual de una manera u otra, también tengo varias instalaciones funcionando así en Windows Server 2003/2008. Creo que esta última máquina virtual que comento estaba montada con Server 2008. En todos los casos, el error es el mismo. Además incluso, teniendo ya esta oportunidad, he configurado varias máquinas con Windows XP o W7 para acceso por escritorio remoto. El problema viene a ser el mismo. Puede haber dos o más instancias que se estén ejecutando a la vez, sobre el mismo servidor, con sesiones remotas, y no me permite abrir el mismo puerto en dos instancias diferentes simultáneas. El sistema que tengo montado, se basa (entre otras funcionalidades) que todo el mundo puede avisar a todo el mundo, sin que se establezcan protocolos TCP concretos, por eso utilizo UDP. Y además incluso hay dos programas diferentes (que pueden correr en la misma máquina) que también se comunican a través de UDP. Respecto de los dos programas diferentes lo tenía perfectamente resuelto con 2 puertos diferentes, y así no hay conflictos. Pero claro, esa es la cuestión. Que cuando es una misma máquina, sí que me aparecen conflictos. Gracias de nuevo
__________________
Piensa siempre en positivo ! |
#6
|
||||
|
||||
A bote pronto se me ocurre que puedes usar memoria compartida (shared memory) para poner en ella "el mensaje". Y que las otras aplicaciones, mediante un temporizador (timer) o un hilo alterno (thread), consulten constantemente el contenido de ese bloque de memoria compartida.
Por cierto, ¿qué versión de Delphi usas? Fuera de tema: Es un gusto verte de nuevo en los foros gluglu. ![]() ![]() |
#7
|
||||
|
||||
Gracias de nuevo también por los mensajes de satisfacción por verme de nuevo por aquí !
![]() La solución de la "memoria compartida" también la he pensado pero tendría que hacer alguna consideración adicional para saber si en un caso debo de utilizar una opción y en otro caso, otra opción. Aun así, realmente tampoco es la solución definitiva porque incluso se podrían dar (y de hecho se dan) instalaciones con redes locales donde a uno de los equipos se conectan mediante escritorio remoto y ejecutan una segunda instancia, por lo que es complicado llevar el control de todo ello, compaginando ambas opciones de solución. Incluso había pensado en una solución más 'trivial' que es que cuando haya que mandar un mensaje por UDP, se lleve un 'control' (por ejemplo por la base de datos que es compartida) de los diferentes puertos UDP (uno por cada 'instancia') que están 'activos' y mandar el mismo mensaje en un bucle a todos los puertos UDP que estén configurados. De esta manera en una red local, cada puesto tendría el mismo puerto UDP, pero en una máquina con escritorio remoto, habría dos puertos UDP diferentes, y de esta manera, en realidad, el Broadcast sólo se haría a 2 puertos UDP. En la máquina virtual configurada con los problemas del inicio de este hilo, hay 10 usuarios remotos creados, por lo que se 'solucionaría' con 10 puertos UDP diferentes y un bucle que envíe broadcast a esos 10 puertos. Es una solución creo que 'chapucilla', por eso intentaba encontrar algo 'bien hecho'. También he visto por ahí la opción del SO_REUSEADDR, pero entiendo que esa opción de socket sólo está disponible para los clientes, y no para los servers, por lo que creo que tampoco me sirve realmente, porque tiene que haber varios servers, uno por cada instancia, para que cada uno esté igualmente escuchando. Ahora mismo estoy con Delphi XE2. ![]()
__________________
Piensa siempre en positivo ! Última edición por gluglu fecha: 09-01-2013 a las 22:00:35. |
#8
|
||||
|
||||
Alguien me podría ayudar con esta información, por favor ?
Ni sé cómo se podría aplicar el Patch que indican, ni sé cómo se podría actualizar a alguna versión de Indy que contenga las modificaciones que indica Remy Lebeau. Gracias Añado : Más Información
__________________
Piensa siempre en positivo ! Última edición por gluglu fecha: 09-01-2013 a las 22:52:29. |
#9
|
||||
|
||||
Ese patch, creo puede ser de un sistema de versionamiento (git, mercurial, svn). si lo abres verás que es la información de como modificar un archivo del repositorio de Indy.
Podrías probar bajandote el fuente de los indy o desde el mismo SVN.
__________________
Buena caza y buen remar... http://mivaler.blogspot.com |
#10
|
||||
|
||||
Como indicaba en mi post anterior, aquí se indican las modificaciones a realizar en los fuentes de Indy.
Lo he hecho todo de acuerdo a lo indicado. Incluso aquí está la versión completa de IdUDPServer.pas, pero al intentar recompilar los componentes Indy, me lanza el error : [DCC Error] IdUDPServer.pas(153): E2147 Property 'ReuseSocket' does not exist in base class ![]()
__________________
Piensa siempre en positivo ! |
#11
|
||||
|
||||
En el Patch, el código es correcto. En la página que indicaba en el último post, las indicaciones y el fichero IdUDPServer.pas no son correctos.
__________________
Piensa siempre en positivo ! |
#12
|
||||
|
||||
Bueno, .... pues tampoco.
La última versión de Indy10, como indica movorack, está en el link que adjunta. Observando ahí la unidad IdUDPServer.pas, el código sí que es el que se describía anteriormente. .... hay que ser un experto (al menos parece que yo no lo soy) para instalar la última versión se Indy (sustituirla por la que tengo actualmente). A ver si lo consigo .... cualquier ayuda es bienvenida !
__________________
Piensa siempre en positivo ! |
#14
|
|||
|
|||
Se me ocurre una solución ...
Crear una aplicación que se ejecute como un servicio de windows, de este modo solo habrá una instancia independientemente de los clientes que se conecten por escritorio remoto. Esta aplicación seria la que este a la escucha por un puerto UDP, y ademas tambien tendria que esperar conexiones por un puerto TCP. Su funcionamiento seria sencillo, los clientes se conectan por el puerto TCP y mantienen activa la conexión esperando a que llegue algún mensaje, por su parte cuando llega algun mensaje por el puerto UDP lo reenviamos a todos los clientes que estén conectados por TCP. Esta solución tiene varias ventajas:
Saludos |
#15
|
|||
|
|||
Se me ocurre otra solución más
![]() quizá aun mas sencilla de implementar. Volvemos a la idea de un servicio por equipo, pero ahora el servicio solo escucha por un puerto UDP (en un puerto predeterminado). Cada vez que recibe un mensaje, guarda la IP y el puerto de origen en una lista y luego reenvía el mensaje a todos los demás que se encuentren en esa lista y se encuentren en el mismo equipo. Tu aplicación solamente tendría que ponerse a la escucha por un puerto UDP (uno aleatorio que este libre) y desde ese mismo puerto enviar los mensajes a la dirección de broadcast, al puerto predeterminado, como hacia antes. El primer mensaje lo podemos enviar nada mas arrancar, solamente para darnos de alta en la lista, y a partir de hay recibiremos los siguientes mensajes que envíen los demás. Es importante que el servicio solo reenvíe los mensajes a las direcciones IP de su propio equipo, de lo contrario si tenemos el servicio en varios equipos podríamos encontramos en un bucle de mensajes broadcast de un equipo a otro. ... le seguiré dando vueltas ... puede que se me ocurra algo mas ![]() |
#16
|
||||
|
||||
Buenas,
no hay mucha más vuelta que dar que la que indica WkaymQ48. Cuando abres dos sesiones en el mismo equipo vía terminal S, la primera instancia del equipo captura el puerto, y las siguientes se encuentran con el puerto bloqueado porque quieren utilizar el mismo puerto de la misma máquina. En este caso, cada sesión no tiene una ip propia, es la misma ya que las sesiones son en el mismo equipo. Si tuviesemos equipos virtualizados ( vmware, virtual server, ... ) sí funcionaría, ya que abrimos equipos completos aunque se ejecuten en la misma máquina. Cada uno de ellos tiene su propia ip y funcionaría. Por lo tanto, la solución pasaría por hacer un proceso, servicio o similar que se ejecute en cada equipo y que sea ése quien gestione los mensajes udp. Ahora, tendría que tener algún mecanismo para saber cuantas instancias de la aplicación tiene abiertas para que todas se enteren. Otra solución es la que has comentado, hacer una tabla de equipos y puertos y gestionar las comunicaciones vía tabla. Para eso puede ser más sencillo poner un timer y que lea la tabla para que cada aplicación sepa si tiene que refrescarse o hacer algo. Sigues teniendo el problema de que debes saber cuantas aplicaciones tienes abiertas por equipo ( ip + usuario por ejemplo ). Un saludo
__________________
Cuando los grillos cantan, es que es de noche - viejo proverbio chino - |
#17
|
||||
|
||||
![]() Amigo GluGlu, finalmente has encontrado alguna solución a esto?... Estoy por pasar por este mismo inconveniente.
Tengo una aplicación "MyApp.exe" donde cada usuario levanta una instancia de ella, con conexiones de Escritorio Remoto. Incluso, en la sesion del Administrador en el propio servidor (WinServer2008) ciertas veces existe tambien otra instancia en ejecución de dicho programa. Además de esto, un segundo ejecutable "Monitor.exe", está siempre en funcionamiento en la sesion del Administrador y realiza un proceso donde las distintas etapas del mismo deben ser notificadas a la/las instancias del programa "MyApp.exe" Actualmente lo tenía resuelto mediante el uso de Messages de Windows, esto es: Desde el programa "Monitor.exe" cada vez que se necesita notificar algo, se invoca la función SendAppMessage() que hace esto:
Por otro lado, el programa "MyApp.exe", siempre está "a la escucha" de esos mensajes mediante un evento que se dispara de forma automática cuando aparece un mensaje invocando al proceso RecibirAppAmessage() que es este:
Lo malo de esto es que, una vez que "MyApp.exe" "publica" el mensaje, lo toma la primera sesion abierta de "MyApp.exe" que logra mostrar el mensaje en su pantalla, pero el resto de las instancias no reciben nada. O sea, lo consume la primera instancia abierta y "se borra" para el resto. Debido a esto, estaba pensando en realizar mensajes UDP, pero me encuentro con el problema planteado aqui de las instancias de Escritorio Remoto y el problema de la apertura del PORT. Como has resuelto esto?
__________________
Gracias de antemano por vuestra ayuda. ·.:*:.·Yako·.:*:.· |
#18
|
||||
|
||||
El problema lo tienes porque usas FindWindow para localizar el Handle de la ventana donde enviarás el mensaje. Debes enumerarlas todas y enviar el mensaje a las que correspondan con tu App, normalmente las conocerás por el nombre de la clase de ventana. Revisa EnumWindows y GetClassName.
Saludos. |
#19
|
||||
|
||||
Cita:
Todas las instancias de RDP levantan el mismo "MyApp.exe". En el ejemplo quedó el verdadero nombre, pero digamos que lo que se intenta con esa linea es enviar el mensaje a ese EXE y no a otro. Sería algomo como esto: Tal vez esto no sea la mejor solución con RDP y es por eso mi consulta, para saber si hay algo mejor. ![]()
__________________
Gracias de antemano por vuestra ayuda. ·.:*:.·Yako·.:*:.· |
#20
|
||||
|
||||
Cita:
Otra solución con sockets es implementar en MyApp un hilo con un cliente y que Monitor.exe sea un servidor. Si el protocolo es UDP no hace falta conexión previa u puedes enviar un datagrama UDP a la IP Broadcast con lo que todas las instancias de MyApp, lo recibirán. Previamente has de calcular la dirección Broadcast de tu red. Saludos. |
![]() |
|
|
![]() |
||||
Tema | Autor | Foro | Respuestas | Último mensaje |
Dos instancias de SQL Server parecen ser la misma | Faust | MS SQL Server | 2 | 21-10-2011 23:13:07 |
¿Cómo usar mutex e impedir dos instancias de la misma app? | Blaster | OOP | 1 | 11-08-2008 04:05:29 |
Cuantas instancias de nuestro exe están corriendo | seoane | Trucos | 3 | 06-03-2007 01:58:41 |
Compartir "objetos" entre varias instancias | mafebresv | Varios | 4 | 16-01-2006 23:38:23 |
Como evitar 2 instancias de una misma ventana hija | edgusano | .NET | 5 | 12-12-2005 16:40:40 |
![]() |
|