Capítulo perteneciente al curso de programación C/C++ LordPakus
Hola a todos,
El capítulo de hoy se centrará en programar un servidor de web html.
Un servidor web no es más un programa que usa los sockets para dar información que pueden representar los navegadores ( html )
Si nosotros montamos un servidor como el del capitulo anterior pero que está vez envie html al cliente ya tendremos un servidor web bien sencillo.
El código es el siguiente:
#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[512];
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[512];
int bytes;
//Iniciamos el servidor
res = InitServer(&local,&servidor, PUERTO);
if ( res )
return res;
while(1)
{
//Esperamos que se nos conecte un cliente
WaitConnection(&servidor,&nueva_conexion);
std::cout << "Conecction received" << std::endl;
bytes = WaitMessage(nueva_conexion,buffer);
if(bytes > 0)
std::cout << "Buffer: " << buffer << " - Bytes recibidos: " << bytes << std::endl;
SendMessage(nueva_conexion,"<HTML><HEAD><TITLE>Un Titulo para el Browser de turno </TITLE></HEAD><BODY><H3>Pongamos un subtítulo<H3></BODY></HTML>");
closesocket(nueva_conexion); // Lo desconectamos!
}
return 0;
}
int main()
{
char opcion;
int res;
if(WSAStartup(MAKEWORD(2,2), &wsa))
return error();
std::cout << "Iniciando LordPakus WebServer" << std::endl;
res = Server();
if(res)
return res;
WSACleanup();
system("PAUSE");
return 0;
}
Espero que os haya gustado. Para probarlo solo debéis arrancar vuestro navegador y en la ruta ponerle 127.0.0.1:8080. Ya vereis los resultados.
Nos vemos
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.
domingo, 23 de septiembre de 2012
jueves, 13 de septiembre de 2012
Curso de sockets. Capitulo 1
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;
}
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;
}
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...
-
<< 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, Este tutorial intenta ser e...
-
<< Capítulo anterior Artículos Relacionados Capítulo siguiente >> Hola a todos... Un compañero vuestro ha...
-
Hola a todos... He aquí la primera entrega "Como crear tu propio motor de videojuegos y no morir en el intento". Antes que nada ...
-
Hola a todos Ya que he recibido un par de mails pidiéndome información sobre SEO, os adjunto unos cuantos trucos que he ido aprendiendo du...
-
<< Capítulo anterior Artículos Relacionados Capítulo siguiente >> El c apitulo de hoy trata sobre las instrucc...