Ir al contenido

publicidad
publicidad

Foto

Duda sobre redes


Este tema ha sido archivado. Esto significa que no puedes responder en este tema.
18 respuestas en este tema

#1

Escrito 16 septiembre 2010 - 22:18

Veamos, para mi juego quiero introducir un modo cooperativo, pero no quiero que haya servidores de por enmedio.

Me explico mejor: Quiero que el coop sea de 2 jugadores, 1 hace de host y el otro hace de cliente. Entonces me gustaría saber estas cosas:

1. Si es posible crear una aplicación de este modo, y si puede ser que no sea local. Es decir, que 2 ordenadores remotos que no comparten red, se conecten a traves de internet sin un servidor externo, solo que 1 de los PCs haga de servidor y otro de cliente.

2. La aplicación la hago para XNA o C#. PD: En XNA NO se puede usar GamesForWindows, así que esa opcion queda desestimada.

3. Si fuera posible, como deberia saber que IP debo usar para la conexion? QUiero decir, que del host debo obtener una IP, pero hay varias IPs (lo compruevo haciendo ipconfig en el msdos de windows XP)

#2

Escrito 16 septiembre 2010 - 23:09

Eso que pides se hace con sockets. Si lo quieres para XNA... hay por ahi una libreria llamada "Lingred" que dicen que va bastante bien, aunque no la he probado.

Un saludo

  • deviax

  • Methuselah

  • vida restante: 100%
  • Registrado: 23 mar 2005
  • Mensajes: 182
#3

Escrito 17 septiembre 2010 - 14:41

Hola NullPointerException,

Como te dice rantamplan87 lo que estás buscando son sockets, que es la forma de comunicar dos aplicaciones a través de la red.

Respecto a librerías que te faciliten el desarrollo de sockets no te sé decir porque hasta ahora yo he programado directamente los sockets, te dejo estos enlaces que están muy bien por la simpleza del ejemplo (son C#, que no te engañe el dominio :P):

UDP client: http://www.java2s.co...leUdpClient.htm
UDP server: http://www.java2s.co...leUdpServer.htm
TCP client: http://www.java2s.co...leTcpClient.htm
TCP server: http://www.java2s.co...leTcpServer.htm

Y para saber la IP del servidor, el "ipconfig" depende de cómo esté configurada tu red puede no darte tu IP pública por lo que no te serviría. Como por lo que comentas entiendo que es un juego en el que empiezas una partida a la que se puede unir un compi, la mejor solución para esto es:
- A la antigua (vía chat o telefonazo, según lo viejo que seas :P), dices la IP pública que tienes en ese momento para que la otra persona se una (utilizando una web como whatismyipaddress.com)
- Resolución de nombres a través de un servicio tipo NO-IP. Yo por ejemplo he programado mi propio NO-IP, que no es más que un programita que publica la IP pública del equipo que hace de servidor en una web cada X minutos y desde los clientes accedo a ese recurso online para saber que IP tiene en ese momento el servidor.

Otro detalle a tener en cuenta es que si quieres poder jugar desde fuera de una red local, seguramente tengas que definir una redirección de puertos en el/los router/s, depende de cuántos y en qué dirección definas los sockets.

Un saludo.

#4

Escrito 17 septiembre 2010 - 17:57

Gracias por la información Deviax. Podrias explciar con más detalle en que consiste eso del NO-IP?

  • deviax

  • Methuselah

  • vida restante: 100%
  • Registrado: 23 mar 2005
  • Mensajes: 182
#5

Escrito 17 septiembre 2010 - 19:23

Hola NullPointerException,

Las dos opciones en plan NO-IP que te comentaba son:

####### Usar NO-IP #######

NO-IP es una página web (http://www.no-ip.com) que ofrece un sistema de resolución de nombres de dominio para IP's dinámicas (entre otros servicios).

La idea consiste en que tú te das de alta en su servicio, diciéndole que quieres tener por ejemplo el nombre de dominio "NullPointerException.no-ip.org", a continuación, de su Web descargas un programa que instalarías en tu ordenador y lo configuras con la cuenta que has dado de alta en su web.

El resultado de hacer todo esto es que cada X minutos, el programa le dice al servidor de NO-IP que está instalado en un ordenador con la IP pública laquesea, de modo que cualquiera que intente resolver el nombre de dominio "NullPointerException.no-ip.org", obtendrá la IP pública de la máquina donde está instalado el programa de NO-IP.


Esta solución aplicada a tu juego consistiría en dar de alta una cuenta en NO-IP e instalar y configurar el programa para que publique la IP pública del ordenador donde se ejecuta el juego que haga las veces de servidor.
La idea está muy bien siempre que el servidor sea la misma máquina.., en el momento en el que le pases el juego a un colega y quiera hacer él de servidor pues tendría que montarse otra vez toda la historia para él.

####### Crear un NO-IP #######

Otra solución es que te hagas una implementación de un sistema "similar", yo por ejemplo de momento lo he resuelto a lo rápido del siguiente modo:
- Hice un programa que cada X minutos se conecta a una página web que lee de un fichero de configuración
- Tengo una página Web en un dominio gratuito con un código PHP que lo que hace es que cada vez que alguien accede a ella escribe en un fichero de texto la IP de la persona que se ha conectado a la web

Entonces el servidor en el arranque ejecuta el programa que se conecta a la Web y que se encarga de publicar en un fichero de texto online la IP del servidor, y finalmente el cliente sólo tiene que leer del fichero colgado en la Web la IP del servidor, que lo puedes hacer por programación que quedaría mucho más elegante, o decirle a la gente "te metes en esta Web y copias y pegas la IP en el juego".

Un saludo!.

#6

Escrito 18 septiembre 2010 - 18:30

Gracias por la información Deviax, investigaré mas a fondo eso que me has dicho

  • deviax

  • Methuselah

  • vida restante: 100%
  • Registrado: 23 mar 2005
  • Mensajes: 182
#7

Escrito 19 septiembre 2010 - 11:07

Gracias por la información Deviax, investigaré mas a fondo eso que me has dicho


Nada ;)

#8

Escrito 28 septiembre 2010 - 05:12

Hola de nuevo,

al final he decidido crear una conexion LAN en formato UDP. El problema que tengo ahora es que no se como podria de alguna forma gestionar los multiples clientes. Yo tengo entendido que en TCP hay un socket de escucha y luego haces un thread por cada cliente y gestionas los datos.

En UDP la cosa es diferente, puesto que con que sepas la IP y el puerto del cliente tu envias y si llega, llega y si no llega, no llega.

Quiero que mi servidor haga lo siguiente:

1. Envie y reciba los datos necesarios
2. Pueda kickear a clientes (cortar la conexion con algun cliente especifico)
3. Que el servidor escuche conexiones entrantes mientras el numero de clientes no exceda el máximo.

Mis preguntas son:

1 - Como gestionariais los diversos clientes? Es decir, como los guardariais? Yo he pensado en estas 3 opciones:

a) Crear un struct formado por el socket del cliente, id de sesion y el thread y guardar cada struct en un array.

b) Crear una lista (o array) de sockets.

c) Crear una lista (o array) de threads (esta creo que es inviable)

2 - Esta pregunta es más centrada en C#: Que me recomendais hacer, usar las clases UDPClient o usar Sockets? Que diferencia hay?

3 - Tengo entendido que en UDP se envian datagaramas, mi pregunta es: Envio array de bytes mediante un buffer, que tamaño seria el adecuado? Mi idea es ponerlo de 1mbyte (1024 bytes), aunque no se si eso esta bien o no.

4 - Quiero dar el ping a los usuarios para que vean la latencia en ms. Como podria hacerlo?

5 - Para forzar una desconexion con el client que hago, desconecto el socket y ya esta, o tambien deberia abortar el thread?

Cualquier respuesta a mi pregunta seria de agradecer.

  • Sante05

  • Methuselah

  • vida restante: 100%
  • Registrado: 21 jul 2001
  • Mensajes: 182
#9

Escrito 28 septiembre 2010 - 21:05

Yo tengo entendido que en TCP hay un socket de escucha y luego haces un thread por cada cliente y gestionas los datos.


No necesariamente. Se pueden gestionar varios sockets en la misma hebra.

1 - Como gestionariais los diversos clientes? Es decir, como los guardariais? Yo he pensado en estas 3 opciones:

a) Crear un struct formado por el socket del cliente, id de sesion y el thread y guardar cada struct en un array.

b) Crear una lista (o array) de sockets.

c) Crear una lista (o array) de threads (esta creo que es inviable)


Yo crearía un struct (o mejor aún, una clase XD) para cada cliente, con su dirección IP como un campo más. Cada cliente debería estar identificado unívocamente (con un id que no se repita). Después metería los clientes en una lista (no un array), o algún tipo de mapa, si me siento con la vena optimizadora.


3 - Tengo entendido que en UDP se envian datagaramas, mi pregunta es: Envio array de bytes mediante un buffer, que tamaño seria el adecuado? Mi idea es ponerlo de 1mbyte (1024 bytes), aunque no se si eso esta bien o no.


Al límite teórico no le hagas caso, el límite práctico suele ser de muy pequeño. 1Kb o así puede ser un buen tamaño. Si necesitas enviar datos más grandes, pártelos en varios paquetes. Recuerda que los datagramas NO tienen porqué llegar en orden, así que tendrás que ordenarlos tú en el destino. Si tienes que enviar muchos datos grandes a lo mejor UDP no es la mejor solución.

4 - Quiero dar el ping a los usuarios para que vean la latencia en ms. Como podria hacerlo?


Envía un datagrama al servidor desde el cliente y guarda el instante en que lo envías. Cuando el servidor lo reciba haz que responda, y cuando el cliente reciba la respuesta mides el tiempo que ha tardado.

5 - Para forzar una desconexion con el client que hago, desconecto el socket y ya esta, o tambien deberia abortar el thread?


En UDP no hay conexión, asi que "desconectar" a un cliente es lo mismo que dejar de hacer caso a sus paquetes y no enviarle ninguno más. Si quieres ser educado, envíale un mensaje de desconexión para que el cliente sepa que ya no debe enviar más datos.


Ah, un punto importante sobre todo esto: Si vas a hacer que uno de los ordenadores haga de servidor te vas a encontrar con varios problemas relacionados con la presencia de NATs en la red. Primero: existen dos IPs, la IP pública (IP de la NAT), y la privada (la del ordenador en la subred), por lo que el primer paso es comunicar la IP pública del host a los demás, teniendo en cuenta que en el ordenador sólo conoces la privada.

Segundo: la NAT probablemente esté configurada para rechazar paquetes entrantes por defecto. Para solventar esto existen varias técnicas (como pueda ser UDP hole punching). Esto se sale un poco de lo que puedo contarte aquí, asi que aqui tienes un enlace con más info: http://en.wikipedia....aversal_problem

  • deviax

  • Methuselah

  • vida restante: 100%
  • Registrado: 23 mar 2005
  • Mensajes: 182
#10

Escrito 28 septiembre 2010 - 23:38

A ver si puedo aportar algo adicional, aunque Sante05 ya ha hecho prácticamente todo el trabajo,

Como dices que vas a tirar por UDP en una LAN lo enfoco hacia eso:

1 - Como gestionariais los diversos clientes? Es decir, como los guardariais? Yo he pensado en estas 3 opciones:

a) Crear un struct formado por el socket del cliente, id de sesion y el thread y guardar cada struct en un array.

b) Crear una lista (o array) de sockets.

c) Crear una lista (o array) de threads (esta creo que es inviable)


Al ser UDP crearía 2 threads en el servidor y otros 2 en el cliente, uno para manejar la lógica del juego y otro para manejar las comunicaciones (envío y recepción de datos).

Como decía Sante05, en C# puedes crearte una clase Cliente que contenga la IP del jugador además de otros datos que te puedan interesar (nombre de usuario, estado del juego, etc), y mientras que de verdad te centres en una LAN, como identificador del cliente puedes usar la IP, ya que no tendrás dos equipos con la misma y así te ahorras almacenar y comunicar más información.

2 - Esta pregunta es más centrada en C#: Que me recomendais hacer, usar las clases UDPClient o usar Sockets? Que diferencia hay?


Yo te diría que sockets porque siempre tiendo a lo que esté a más bajo nivel, de este modo tú te lo guisas y tú te lo comes y te ahorras limitaciones que pueda tener la clase UDPClient (en el enlace al tutorial Simple Udp Client que puse en el otro post habrás visto que usar Sockets no puede ser más sencillo).

3 - Tengo entendido que en UDP se envian datagaramas, mi pregunta es: Envio array de bytes mediante un buffer, que tamaño seria el adecuado? Mi idea es ponerlo de 1mbyte (1024 bytes), aunque no se si eso esta bien o no.


Como te dice Sante05 apunta siempre a lo mínimo que puedas, un tamaño seguro son 512B y salvo que tuvieras paquetes de tamaño superior a 1KB no pensaría en implementar tu propia fragmentación pero..., ¿de verdad vas a mandar tanta información?, para enviar posiciones, acciones de un jugador, etc, no creo que necesites más de 20B, el truco es que asocies cada acción a un número y así sólo tienes que enviar de 1 a 5B más otros 2 a 10B para indicar la dirección de la acción o sobre donde actúa la acción.

Por darte ideas, yo para todo el tema de la transmisión de datos programé una clase Paquete que inicialmente no contiene nada y que me permite agregarle enteros y strings, simplificando la manera en que funciona, sus primeros bytes indican el tamaño del paquete, y a continuación están los datos acompañados de una cabecera de tamaño, algo así como "64hola", donde 6 es el tamaño de todo el paquete, 4 indica que empieza un segmento de 4 bytes de datos, y la palabra "hola" es el dato, de este modo te ahorras el tener un tamaño fijo y ahorras en ancho de banda.

4 - Quiero dar el ping a los usuarios para que vean la latencia en ms. Como podria hacerlo?


Nada más que añadir

5 - Para forzar una desconexion con el client que hago, desconecto el socket y ya esta, o tambien deberia abortar el thread?


Nada más que añadir tampoco.


Lo único que comento a parte es lo que te dice Sante05 del NAT, que en caso de una red LAN no debería afectarte, otra cosa es que las conexiones salgan a través de internet...

Un saludo.

#11

Escrito 29 septiembre 2010 - 17:43

Vale, ya me va quedando más claro.

Si me surgen más dudas ya preguntaré

#12

Escrito 30 diciembre 2010 - 20:26

***PARA LA MODERACION: Refloto este hilo porque me gustaria reaprovecharlo para solventar unas dudas que me han surgido ahora. Asi que os pido que no me cerreis el hilo ni me expulseis, porque considero que lo hago con un buen motivo.***

A ver, tengo un problema que podriamos decir que es gordo. Al final he decidido establecer una conexion en lan, el problema es que el servidor y el cliente comparten IP, por lo que el servidor se enviaria a si mismo los datos y el cliente no los recibiria. Alguien sabria decirme que deberia hacer para evitar esto?

Os digo lo que me pasa para entenderlo mejor:

Cada usuario tiene un nombre de jugador. Tengo 2 usuarios, uno para el cliente y otro para el servidor.

El servidor ejecuta la sala de espera, eso sale bien.

Cuando se conecta el cliente, le envia el nombre de usuario del cliente. Pero el servidor, al intentar enviarle su nombre de usuario al cliente, lo recibe él mismo.

Salidra algo asi:

"Servidor" -> se añade su nombre al crear la sala de espera, esto esta bien.

"Cliente" -> Esta bien, el cliente envia su nombre de usuario al servidor y éste lo recibe.

"Servidor" -> ESTO ESTA MAL. En teoria deberia recibirlo el cliente y no el servidor, pero lo dicho, el problema es que los 2 tienen la misma IP.

Alguien podria orientarme como podria hacerlo en LAN teniendo en cuenta el problema de la IP?

PD: Ejecuto la misma aplicacion 2 veces en el mismo PC, una como cliente y otra como servidor. Lo digo por si puede ser un dato interesante.

Gracias por adelantado

#13

Escrito 30 diciembre 2010 - 21:33

Como que dos equipos tienen la misma IP? Eso no puede ser, cada uno tendra su IP.
Ves a cada maquina y ejecuta en la consola "ipconfig" y mira la ip que tiene cada uno.
Si estan en la misma red local, seran 192.168.1.X

Un saludo

#14

Escrito 30 diciembre 2010 - 22:04

Te explico:

La IP del servidor es 127.0.0.1, sin embargo, no se que pasa que al establecer una conexion se envia a si mismo los datos.

Lo que hago es utilizar un IPAdress.loopback, puesto que si uso un IPAdress.Any, me da un error

  • Btc

  • Adramalech

  • vida restante: 100%
  • Registrado: 15 oct 2007
  • Mensajes: 1.932
#15

Escrito 30 diciembre 2010 - 22:14

Eeem... yo no tengo mucha idea del tema, pero si te sirve un ejemplo en VB.NET, OllyDBG tenia una entrada en su blog en la que hacía precisamente eso (o eso creo), por si puede serte de ayuda.

Lo que si pasa, es que enviaba cadenas de texto, pero si lo adaptas un poco...

Un saludo, Btc


Este tema ha sido archivado. Esto significa que no puedes responder en este tema.
publicidad
publicidad