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.
¿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!
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!
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;
}
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.=)
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)
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.=)
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
Hostias!
Merci, ni se me habia pasado por la cabeza. xDD
Gracias!!