Capítulo perteneciente al curso de programación C/C++ LordPakus
Hola a todos,
Por petición popular ( y tal y como prometí) os adjunto un tutorial del uso de sockets en C sobre windows.
Los sockets no son más que la herramienta que nos da el sistema operativo para conectarnos a una red desde nuestro programa. Normalmente son dependientes de la API del SO, así que me restringo solamente a sistemas windows. Si algún valiente quiere hacer la versión para Linux, adelante!
Casi todas las estructuras de red actuales se basan en un configuración cliente-servidor. Es decir, tenemos un ordenador que se limita a escuchar por un puerto y otro ordenador que "ataca" a ese servidor en ese puerto. A través de esa información se realiza la comunicación.
Al contrario que en otros lenguajes, el tema de red en C no es ni fácil ni intuitivo (algo malo tenia que tener :D ), así que me limitaré a copiaros el código para que podáis hacer vuestras pruebas. cualquier duda que tengáis hacedmela llegar.
En breves dias encapsularé el código en C++ para que sea más legible.
Espero que os guste, nos vemos:
main.c
#include <iostream>
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#pragma comment(lib, "Ws2_32.lib")
#define PUERTO 8080
WSADATA wsa;
int error()
{
std::cout << "Error #" << GetLastError() << std::endl;
WSACleanup();
getchar();
return 0;
}
int InitServer(sockaddr_in *local, SOCKET * servidor, int puerto)
{
local->sin_port = htons(puerto); // Puerto a la escucha.
local->sin_family = AF_INET; // Debe ser AF_INET.
local->sin_addr.S_un.S_addr = INADDR_ANY; // Usar cualquier dirección.
*servidor = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // Protocolo TCP
if(*servidor == INVALID_SOCKET)
return error();
if(bind(*servidor, (sockaddr*)local, sizeof(sockaddr)) == SOCKET_ERROR)
return error();
if(listen(*servidor, 1) == SOCKET_ERROR) // Colocamos el servidor a la escucha.
return error();
std::cout << "Servidor a la escucha por el puerto " << puerto << ", esperando conexión." << std::endl;
return 0;
}
void WaitConnection(SOCKET *servidor, SOCKET * nueva_conexion )
{
do
{
*nueva_conexion = accept(*servidor, NULL, NULL); // Esperamos una conexión entrante y la aceptamos.
} while(*nueva_conexion == SOCKET_ERROR);
}
void SendMessage(SOCKET conexion,char *str)
{
send(conexion,str,strlen(str),0);
}
int WaitMessage(SOCKET conexion, char *bufout)
{
int bytes_recv;
char buffer[256];
memset(buffer, 0, sizeof(buffer)); // Limpiamos el buffer temporal
memset(bufout, 0, sizeof(buffer)); // Limpiamos el buffer de salida.
do
{
bytes_recv = recv(conexion, buffer, sizeof(buffer), 0); // Esperamos para recibir datos...
} while(bytes_recv == 0 && bytes_recv != SOCKET_ERROR);
//Copiamos el buffer temporal en el de salida
memcpy(bufout,buffer,bytes_recv);
return bytes_recv;
}
int Server(void)
{
int res;
SOCKET servidor, nueva_conexion;
sockaddr_in local;
char buffer[256];
int bytes;
//Iniciamos el servidor
res = InitServer(&local,&servidor, PUERTO);
if ( res )
return res;
//Esperamos que se nos conecte un cliente
WaitConnection(&servidor,&nueva_conexion);
SendMessage(nueva_conexion,"Servidor C++!");
bytes = WaitMessage(nueva_conexion,buffer);
if(bytes > 0)
std::cout << "Buffer: " << buffer << " - Bytes recibidos: " << bytes << std::endl;
closesocket(nueva_conexion); // Lo desconectamos!
return 0;
}
int InitClient(sockaddr_in *conexion,SOCKET * cliente, char *ip, int puerto )
{
conexion->sin_family = AF_INET;
conexion->sin_port = htons(PUERTO); // Puerto donde nos conectaremos
conexion->sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
//Todo: Implementar tb por nombre de host
// conexion->.sin_addr = *((in_addr*)gethostbyname("localhost")->h_addr); // Host a donde nos conectaremos
*cliente = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // Protocolo TCP
if(*cliente == INVALID_SOCKET)
return error();
if(connect(*cliente, (sockaddr*)conexion, sizeof(sockaddr))) // Conectamos con el servidor
return error();
return 0;
}
int Client(void)
{
sockaddr_in conexion;
SOCKET cliente;
char buffer[256];
int bytes;
int res;
res = InitClient(&conexion,&cliente,"127.0.0.1",PUERTO);
if(res)
return res;
SendMessage(cliente,"Hola, soy un cliente en C++!");
bytes = WaitMessage(cliente,buffer);
if(bytes > 0)
std::cout << "Buffer: " << buffer << " - Bytes recibidos: " << bytes << std::endl;
closesocket(cliente); // Finalmente desconectamos...
return 0;
}
int main()
{
char opcion;
int res;
if(WSAStartup(MAKEWORD(2,2), &wsa))
return error();
do
{
std::cout << "1-Servidor o 2-Cliente?" << std::endl;
opcion = getchar();
}
while( (opcion != '1') && (opcion != '2'));
if(opcion == '1')
{
std::cout << "Iniciando servidor" << std::endl;
res = Server();
}
else
{
std::cout << "Iniciando cliente" << std::endl;
res = Client();
}
if(res)
return res;
WSACleanup();
system("PAUSE");
return 0;
}
Blog de programación enfocado a estudiantes principiantes de C/C++ en español. Dispone de cursos de todos los niveles y para multitud de usos.
-
- Tutoriales de programación
- Teoría informática
- Metodologías Ágiles
- Proyectos
- Electrónica
- FAQ
- MicroTecnoPedia
- Otras webs del mismo autor
Entradas populares
-
Una pregunta que me hacen en muchas ocasiones es ¿¿qué significa %2?? La respuesta tiene dos acepciones en función de si lo estamos u...
-
<< Ejemplo anterior Artículos Relacionados Ejemplo siguiente >> Hola a todos, ASCII Art es el hecho de hacer di...
-
Articulo perteneciente a : Referencias de programación Hola a todos Os pongo una aportación que a más de uno le irá bien, un resumen de ...
-
Capítulo perteneciente al tutorial de opengl desde cero Hola a todos, Este capítulo tal vez es de lo más complicados de la teoría necesa...
-
<< Capítulo anterior Artículos Relacionados Capítulo siguiente >> Hola a todos, Este tutorial intenta ser e...
-
Hola a todos... He aquí la primera entrega "Como crear tu propio motor de videojuegos y no morir en el intento". Antes que nada ...
-
<< Ejemplo anterior Artículos Relacionados Ejemplo siguiente >> Hola a todos, El ejercicio de hoy se basa en c...
-
<< Capítulo anterior Artículos Relacionados Capítulo siguiente >> Hola a todos... Un compañero vuestro ha...
-
Hola a todos... En muchas ocasiones un programador ve frustrado un proyecto al faltarle un artista de audio y/o imagen que le complemente ...
-
<< Gurú anterior Gurús de la programación John Carmack Robert C. Martin (Uncle Bob) Kent Beck Martín Fowler Ward C...
Muchas gracias por los tutoriales.
ResponderEliminarTengo algunas dudas, espero me pueda orientar un poco.
Le comento mi situación: estoy estudiando Ingeniería de Sistemas, y en varios de los cursos que llevo y llevaré se trata sobre programación. Sinceramente, creo que es lo que más me agrada de la carrrera. A nosotros nos dijeron que aprenderemos muchas cosas y que posteriormente, será recomendable que estudiemos alguna especialización en aquello que más nos interese.
He llevado cursos básicos sobre C++ y Visual C++ (creando proyectos del tipo "Windows Forms" usando Visual Studio), y sinceramente, los temas no son difíciles como lo creía en un inicio. Cada vez que tenía dudas he preguntado en algunos foros y me respondían muy bien. El punto es que, aunque haya ido un poco más allá de los temas que me correspondían en clases, no he ido tan allá como debería haber sido.
A lo que me refiero es que sólo he aprendido lo básico sobre C++ y ahora estoy llevando Java. Y como que no hay mucha diferencia entre estos lenguajes. El punto es que, debemos averiguar sobre muchos temas nuevos y los exámenes son muy teóricos. Eso ha hecho que de alguna forma haya dejado de practicar como lo hacía antes.
Es decir, los ejercicios sobre realizar algunos cálculos ya no me parecen muy interesantes... y justo ahora mismo he vuelto a recordar aquello por lo que siempre tuve curiosidad pero que lo dejé por creerlo muy lejano.
Es sobre el tema de Sockets, si es que así se le puede llamar: lo que quisiera aprender es sobre cómo crear programas que hagan uso del internet. Es decir, por ejemplo, cómo crear un muy básico chat o algún juego muy básico en el que puedan competir 2 personas online (cada uno con el mismo programa pero viéndolo de distinta forma).
Lo más probable es que ello involucre muchos temas, pero quisiera empezar a comprenderlos. Tal vez usted pueda darme algunas recomendaciones sobre ello. Y quisiera aprender este tema en Java, ya que, aunque me interese también en C++, actualmente estoy llevando un curso sobre Java y no me gustaría llegar a confundirme.
Gracias nuevamente y espero me pueda ayudar.
Realmente la programación de juegos en red puede llegar a ser extremadamente compleja.
ResponderEliminarSi lo que quieres es aprender sobre el tema hay una libreria que está muy muy bien que se llama rakNet (http://www.jenkinssoftware.com/) que te permite trabajar con red a todos los niveles dejando el código muy limpio y sencillo.
Pruebala y ya me contarás
Animate a hacerlo en Linux!
ResponderEliminarNo entendí nada de la guía Beej...
ya dejé Sistemas Operativos para el próximo año..
no explican absolutamente nada
Buenas,
EliminarRealmente en linux no es tan diferente a Windows.
A ver si me saco tiempo de la manga en algun momento y hago algun tutorial para Linux.