Foros - Stratos

Programadores => Programación en red => Mensaje iniciado por: StarAD en 23 de Mayo de 2007, 12:54:30 PM

Título: 2Players Servidor/Cliente
Publicado por: StarAD en 23 de Mayo de 2007, 12:54:30 PM
Hola:

Llevo tiempo preparando un juego para dos jugadores en red, donde una maquina crea la partida y otro se conecta a este. Despues de un tiempo haciendo el sistema de juego y los graficos ya tengo el juego casi listo para empezar a crear el sistema de red. La verdad es que en el tema de porgramacion en red estoy un poco pajaro y me gustaria que me aconsejarais si para este tipo de juego es mejor que cree desde cero el servidor y cliente o utilice algun tipo de libreria.

Muchas gracias.
Título: 2Players Servidor/Cliente
Publicado por: rcaf en 23 de Mayo de 2007, 06:45:07 PM
¿Con Qué API y lenguaje estás trabajando?

Lo mejor es que utilices alguna biblioteca, como SDL_net.

http://www.libsdl.org/projects/SDL_net/

Si ya sabes el manejo de sockets en linux, usar esta API no será ningún problema, de hecho es más fácil =)

Si no manejas los conceptos de redes, deberías comenzar leyendo sobre los protocolos tcp y udp. Y también sobre sockets. En la red hay demasiada info sobre esto.

Te recomiendo estas dos páginas para aprender más sobre sockets:

http://www.starlinux.net/staticpages/index.php?page=20020720164837437

http://es.tldp.org/Tutoriales/PROG-SOCKETS/prog-sockets.html


Comienza realizando un pequeño programa de prueba, por ejemplo para practicar podrías hacer un servidor que espere los datos de un usuario: user y password, y luego hacer una autentificación de los datos.

El cliente leería desde teclado el user/pwd y los enviaría al servidor que esta escuchando en algún puerto, luego el servidor debería enviar un número, por ejemplo si es 0 la autentificación fallo y si es 1 todo resultó ok.

Lo anterior lo puedes hacer con el protocolo tcp.

Saludos!
Título: 2Players Servidor/Cliente
Publicado por: TheAzazel en 23 de Mayo de 2007, 06:47:29 PM
echa un vistazo a el apartado de red de CRM32Pro, esta construido sobre SDL_net y ya te lo deja todo a tiro para dedicarte a tu juego.

Tan solo debes conocer muy basicamente de que va eso de cliente-servidor :)

ya me diras, saludos!
Título: 2Players Servidor/Cliente
Publicado por: Warchief en 23 de Mayo de 2007, 08:39:31 PM
Apoyo lo de usar/ver CRM32Pro.

Hace poco (Enero) hice una demo simple de un chat usando esa lib, y fue harto sencillo (aparte de contar con la constante ayuda de Az). Si quieres echarle un vistazo:
Ficheros  binarios (http://www.telefonica.net/web2/warchief/WorkSamples/Projects/Videogames-NetWorld/CRM32Pro%20Demo%20-%20Warchief%20Binaries.rar) (funciona en el mismo ordena y por internet claro).
Código fuente VS2005 (http://www.telefonica.net/web2/warchief/WorkSamples/Projects/Videogames-NetWorld/CRM32Pro%20Demo%20-%20Warchief%20Source%20No%20Web.rar) (no incluye las lib necesarias para compilar, como CRM32Pro y Visual Leak Detector)
Página web con info sobre la demo (http://www.telefonica.net/web2/warchief/WorkSamples/Projects/Videogames-NetWorld/NetWorld%20WEB/index.html) (cómo ejecutarlo, elegir el servidor, etc)

En la web hay un par de capturas (se pueden ver a mayor tamaño)
(http://www.telefonica.net/web2/warchief/WorkSamples/Projects/Videogames-NetWorld/NetWorld%20WEB/images/raulClient.jpg)

Por ejemplo, la parte que te interesa para hacer un chat es:

   // Execute chat
   int CClientEntity::ExecuteChat( void *clientOwner )
   {
       // Get the client owner
       CClientEntity *ownerPtr = static_cast< CClientEntity* >( clientOwner );
       // Get engine components
       Engine::IEngineAbstractFactory *enginePtr = ownerPtr->GetEnginePtr();
       Engine::Network::INetwork *networkPtr = enginePtr->GetNetworkPtr();
       Engine::Core::ICore *corePtr = enginePtr->GetCorePtr();

       // Try to connect to server
       if( !networkPtr->Connect( ownerPtr->GetChatServer().c_str(),
                                 ownerPtr->GetChatPort(),
                                 ownerPtr->GetName().c_str(),
                                 ownerPtr->GetChatPassword() ) )
       {  
           // Notify failure
           ownerPtr->OnChatFailed();
       }
       // Ok chat is running
       else {

           // Notify event
           ownerPtr->OnChatConnected();

           // Go now, to get messages!
           ExecuteChatInput( clientOwner );

       }

       return 0;
   }

   //---------------------------------------------------------------------------------------------------------
   
   int CClientEntity::ExecuteChatInput( void *data )
   {
       // Get the client owner
       CClientEntity *ownerPtr = static_cast< CClientEntity* >( data );
       // Get engine components
       Engine::IEngineAbstractFactory *enginePtr = ownerPtr->GetEnginePtr();
       Engine::Network::INetwork *networkPtr = enginePtr->GetNetworkPtr();
       Engine::Core::ICore *corePtr = enginePtr->GetCorePtr();

       // Build up a buffer for data
       static const int MAX_CHAT_MSG = 1024; // Nice
       char buffer[MAX_CHAT_MSG];

       while ( RUN_CHAT ) {

           // Restore buffer
           memset( buffer, 0, MAX_CHAT_MSG );

           // Get data
           Engine::Network::INetwork::TIncomingData ret = networkPtr->ReceiveData( buffer, MAX_CHAT_MSG );

           switch( ret )
           {
               case Engine::Network::INetwork::TID_ERROR:
               case Engine::Network::INetwork::TID_CLOSE:
                   // Notify chat failure
                   if( ownerPtr )
                       ownerPtr->OnConnectionLost();
                   break;
               case Engine::Network::INetwork::TID_NEWCLIENT:
                   if( ownerPtr )
                       ownerPtr->OnNewClient( buffer );
                   break;
               case Engine::Network::INetwork::TID_QUITCLIENT:
                   if( ownerPtr )
                       ownerPtr->OnClientLeft( buffer );
                   break;
               case Engine::Network::INetwork::TID_DATA:
                   if( ownerPtr )
                       ownerPtr->OnIncomingMessage( buffer );                    
                   break;
           }        


           // Small delay
           corePtr->Delay( 100 );

       };

       // Just 0
       return 0;
   }
Título: 2Players Servidor/Cliente
Publicado por: StarAD en 23 de Mayo de 2007, 08:40:39 PM
Gracias por responder tan rapido.

Para mi juego utilizo Ogre3D (C pus pus).

Creo que me mirare la biblioteca SDL_net ya que da la casualidad que ahora mismo acabo de venir de la universidad de hacer una practica sobre shockets en UNIX. :D . No es que conozca todos los detalles sobre programacion con shockets asi que de paso me mirare los articulos.

Muchas gracias!

PD: Coño!! Hemos posteado a la vez!! Pues muchas gracias por el codigo y los links. Ya posteare a ver cual he utilizado y como me ha ido.=)
Título: 2Players Servidor/Cliente
Publicado por: Warchief en 23 de Mayo de 2007, 08:47:00 PM
Cita de: "StarAD"PD: Coño!! Hemos posteado a la vez!! Pues muchas gracias por el codigo y los links. Ya posteare a ver cual he utilizado y como me ha ido.=)

^_^' De hecho acabo de yo modificarlo por última vez (unas 4 en total :D)
Título: 2Players Servidor/Cliente
Publicado por: StarAD en 31 de Mayo de 2007, 12:13:47 PM
Hola:

Al final me he decidido a utilizar la libreria SDL_net. Llevo dias haciendo pruebas y ya he conseguido hacer un servidor y un cliente, pero hay una duda que me corroe.

Para crear la direccion ip utilizo la funcion SDLNet_ResolveHost y le paso la direccion del objeto IPAddress, NULL para el servidor y el puerto. El problema lo tengo con el puerto. Mirando en la documentación y en los ejemplos de la web he visto que para añadir un puerto lo añade haciendo una conversion a Uint16 y para sacarlo por pantalla lo lee tal cual. Si yo hago eso cuando lo voy a leer me sale un numero de puerto que no tiene nada que ver con el que he puesto. Consegui resolver el problema haciendo un conversion a Big Endian con la funcion SDL_SwapBE16 a la hora de añadir el puerto. Todo esto me sirvio para un programa de prueba. Pero ahora que lo estoy implementando en el proyecto del juego me peta y me dice esto   : Couldn't bind to local port.

Ahi van mis preguntas: Porque tengo que hacer un conversion de Little Endian a Big Endian para que me salga el puerto correcto?
Si yo le pongo el puerto 5425 al crear la ip y luego me enseña por pantalla con el print el puerto 12565, en cual de los dos puertos esta escuchando? El problema esta solo al escribirlo por pantalla y de verdad esta escuchando en el puerto 5425?

Espero que me podais ayudar porque es algo que por muchas vueltas y pruevas que hago no llego a nada concluyente.

Gracias por las respuestas.=)
Título: 2Players Servidor/Cliente
Publicado por: blau en 11 de Junio de 2007, 04:52:34 PM
Con el comando netstat puedes ver las conexione sque tienes activas

Ya sabes desde el interprete de comandos, ese maravilloso compañero de fatigas.

Sniff, un saludo
Título: 2Players Servidor/Cliente
Publicado por: StarAD en 12 de Junio de 2007, 01:27:41 PM
Hostias!

Merci, ni se me habia pasado por la cabeza. xDD

Gracias!!