INTRODUCION
Bueno me presento soy chewarrior, y este es un tutorial basico sobre socket en lenguaje C para Windows,desde ahora ya les adelanto que intentare hacer esto los mas ameno y facil posible, este tutorial no tiene la intencion de hacerte un programador profesional, ni explicar cada funcion como si yo fuero uno de ellos, este tutorial esta creado por un principiante para principiantes, no esperes una explicacion detenida y correcta, si no codigo muy basico para hacerte una base sobre como utilizar la libreria socket del lenguaje C.
¿Que es un socket? ¿Para que sirve?
¿Que es un socket?
-Es el proceso cliente y servidor, que se utiliza en internet, todo esto gracias a la libreria de C socket.
¿Para que sirve?
-Para interactuar con los protocolos de internet.
-Ejemplos de familias de protocolos TCP;
-Ftp, smtp, http...
-Ejemplos de familias de protocolo UDP;
-Dhcp,Bootp ,Dns...http://es.wikipedia.org/wiki/Familia_de_protocolos_de_Internet
PD; Si no estas familiarizado con los protocolos de internet, o si no tienes una base basica sobre el lenguaje en C, no vas a poder seguir este tutotial.
Info; http://es.wikipedia.org/wiki/Cliente-servidor
Info; http://es.wikipedia.org/wiki/Familia_de_protocolos_de_Internet
Funciones ¿Cliente y servidor en C (Socket)?
Antes de nada:
En Windows vas a tener que inciar winsock, pero esa funcion deve de ponerse despues de iniciar las structura y la variable para tu socket
Ejemplo;
Código:
int sock;
struct sockaddr_in direccion;
WSADATA wsa; \\ La llamada de winsock tambien se puede poner al principio
WSAStartup(MAKEWORD(2,0),&wsa); \\ 2,0 define la version de winsock que quieres utilizar.
El cliente pasó 1:
Creamos el socket(Es como construir la puerta por lo que ira todo), primero dandole la familia del protocolo, despues el tipo de paquetes que va a recivir o enviar (tipo socket), y por ultimo el tipo de protocolo a utilizar.
Sintaxis:
int sock; \\ definicion del socket
sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
socket(Famaly protocolo,tipo de Socket,Protocolo);
Familia del protocolo:
AF_INET Establece una comunicacion, con cualquier maquina conectada a internet.
AF_UNIX Establece una comunicacion para maquinas locales Linux.
AF_NS Establece una comunicacion para redes Xerox.
AF_CCITT Establece una comunicacion para protocolos CCITT,X25...
Tipo de Socket:
SOCKET_STREAM socket tipo stream, son los utilizados para tcp.
SOCKET_DGRAM tipo sockets para udp.
SOCKET_RAW tipo socket que permite el acesso a bajo nivel, IP.
Protocolo:
PPROTO_TCP lo dice su nombre protocolo tcp.
IPPROTO_UDP lo dice su nombre protocolo udp.
Cliente paso 2:
Primero creamos una structura (struct), en la que definiremos el tipo de protocolo a utilizar para la conexion, despues el puerto por el que deve conectarse nuestro cliente y por ultimo la ip a la que conectara nuestro cliente.
Sintaxis:
Código:
Char ip[15]=”127.0.0.1”;
int puerto=21;
struct sockaddr_in direccion;
direccion.sin_family=AF_INET;
direccion.sin_port=htons(puerto);
direccion.sin_addr.s_addr=inet_addr(ip);
Vamos por partes:
int puerto=21; // defenimos la variable con su puerto
// Otras opciones para almacenar el puerto
#define puerto 21
char ip[15]=”127.0.0.1” // Ip local
// Otra opciones para almacenar la ip
#define ip "127.0.0.1"
struct sockaddr_in direccion; // estructura creada
// Ahora procedemos a insertar la informacion en la structura.
// Date cuanta de que es una structura especial para socket; sin_family,sin_port ....
direccion.sin_family=AF_INET; // AF_inet utilizamos el protocolo tcp (ves a paso 1, familia del protocolo para mas informacion)
direccion.sin_port=htons(puerto); //htons transforma tu numero de puerto a uno entendible para el socket.
direccion.sin_addr.s_addr=inet_addr(ip); // La ip se agrega
Cliente pasó 3:
Despues de crear el socket y la structura con los datos pertinentes, podemos conectar por fin al servidor,con la funcion (connect).
Sintaxis:
connect(sock, (struct sockaddr*)&direccion,sizeof(direccion));
Vamos por partes:
Código:
connect(definicion del socket que creamos en el paso 1,
connect(sock,(Aqui va la structura anteriormente paso 2 creada con todos los datos para conectar,ip,protocolo,puerto)&dirrecion
connect(sock,(struct sockaddr*)&dirrecion,sizeof(Utilizamos el operador sizeof para indicar la longuitud de la estructura)
connect(sock, (struct sockaddr*)&direccion,sizeof(direccion)); \\ Ves como no es tan dificil xd
Cliente pasó 4:
Ahora que ya estamos conectados al servidor,ya podemos enviarle informacion con la funcion (send).
Sintaxis:
char buf[15]=”Hola galaxia”;
send(sock,buf,sizeof(buf),0);
Vamos por partes:
Código:
send(definicion del socket que creamos en el paso 1,
send(sock,variable con la informacion a enviar,
send(sock,buf, Utilizamos el operador sizeof para indicar la longuitud de la variable
send(sock,buf,sizeof(buf),Flag lo dejamos en 0
send(sock,buf,sizeof(buf),0); \\ resultado final, ves como no era tan dificil
Por ultimo:
Cerramos nuestro socket con closesocket(sock);
El servidor:
Es bastante parecido al cliente, se le tiene que crear el socket (Cliente paso 1) y una structura con todos lo datos del server; protocolo, puerto, ip (Cliente paso 2).
Servidor pasó 1:
Con la función bind, asociaremos las estructura y el socket de nuestro servidor, basicamente ponemos a la escucha a nuestro servidor con la ip y puerto especificadas en la estructura struct sockaddr_in server.
Sintaxis:
Código:
WSADATA wsa;
int sock;
struct sockaddr_in server;
WSAStartup(MAKEWORD(2,0),&wsa);
if((sock=socket(AF_INET,SOCK_STREAM,0))==-1){; // creamos el socket, atento en una condicion(if) la funcion devuele -1 si esta falla.
printf("Error creando el socket, saliendo…");
getch();
exit(0);
}
server.sin_family= AF_INET; // familia socket
server.sin_addr.s_addr=INADDR_ANY; // INADDR_ANY es lo mimo que poner local host (127.0.0.1).
server.sin_port=htons(puerto); //Puerto
bind(sock,(struct sockaddr *)&server,sizeof(server)); \\ Esto es lo que no vimos y voy a explicar a continuacion
Vamos por partes:
Código:
bind(definicion del socket que creamos(sock=socket(AF_INET,SOCK_STREAM,0));,
bind(sock,( Aqui va la structura anteriormente creada (struct sockaddr_in server;)con todos los datos del servidor,ip,protocolo,puerto) &server
bind(sock,(struct sockaddr *)&server,sizeof(Utilizamos el operador sizeof para obtener la longuitud de la estructura)
Servidor pasó 2:
Con la funcion listen, pondremos nuestro servidor a la escucha, esperando a que algun cliente se conecte.
Sintaxis:
Vamos por partes:
Código:
listen(definicion del sock creado en el paso 1,)
listen(sock,numero de clientes que se podran conectar al servidor)
Servidor pasó 3:
Ahora deveremos aceptar la conexion del cliente con la funcion accept.
Sintaxis:
Código:
(sock=accept(sock,0,0));
Vamos por partes:
Código:
(sock=accept(defenicion del socket,)
(sock=accept(sock,Lo dejamos en 0,0(Aqui se deveria especificar la longuitud de la estructura)
Servidor pasó 4:
Ahora que el cliente ya a conectado, no ponemos a la espera de la informacion enviada por el cliente con la funcion recv
Sintaxis:
Código:
buffer[20];
recv(sock,buffer,sizeof(buf),0);
Vamos por partes:
Código:
recv(Definicion del socket,
recv(sock,variable en la cual se guaradara la informacion enviada por el cliente
recv(sock,buffer,El operador sizeof informa a la funcion recv,la longitud de la variable)
Por ultimo:
Cerramos nuestro socket con closesocket(sock);
Ejemplo basico del cliente:
Código:
#include <conio.h>
#include <stdio.h>
#include <windows.h>
#include <string.h>
#define ip "127.0.0.1" //ip del servidor
char buf[20];
int puerto=190; // puerto del servidor a conectar
int main()
{
WSADATA wsa; // winshock
int sock;//descriptor del socket.
struct sockaddr_in direccion; //datos del servidor a conectar
WSAStartup(MAKEWORD(2,0),&wsa);
if((sock=socket(AF_INET,SOCK_STREAM,0))==-1 ){ // creamos socket
printf("problema al crear el stock");
getch();
exit(0);
}
else{
direccion.sin_family=AF_INET;// protocolo af inet, visto antes.
direccion.sin_port=htons(puerto);//htons convierte el puerto al formato de red.
direccion.sin_addr.s_addr=inet_addr(ip); // ip del serividor al que vas a conectar
//conectamos al servidor
if(connect(sock,(struct sockaddr*)&direccion,sizeof(direccion))==-1){
printf("Error al conectar");
getch();
exit(0);
}
printf("Conectado correctamente\n");
puts("Mensaje a enviar;");
gets(buf);
if(send(sock,buf,sizeof(buf),0)==-1){
printf("error enviando");
exit(0);
}
puts("Mensaje enviado,pulas una tecla para cerrar el cliente");
getch();
}
return 0;
}
Ejemplo basico del servidor
Código:
#include <stdio.h>
#include <winsock.h>
#include <string.h>
#include <conio.h>
#define puerto 190 // puerto del servidor por el que se conectaran los clientes
main(){
WSADATA wsa; // winshock
int sock;
char buffer[20];
struct sockaddr_in server; // estructura del los datos del server
WSAStartup(MAKEWORD(2,0),&wsa); // Version winshock y start
if((sock=socket(AF_INET,SOCK_STREAM,0))==-1){; // creamos el socket
printf("Error creando el socket");
getch();
exit(0);
}
server.sin_family= AF_INET; // familia socket
server.sin_addr.s_addr=INADDR_ANY; // local host
server.sin_port=htons(puerto); //Puerto
if(bind(sock,(struct sockaddr *)&server,sizeof(server))==-1 ){//Asociamos
printf("error asociando");
getch();
exit(0);
}
printf("Esperando Clientes\n");
listen(sock,2); // Maximos de clientes permitidos 2
if((sock=accept(sock,0,0))<0){ // Aceptamos conexion cliente
printf("error aceptando connexion");
exit(0);
}
puts("Cliente conectado");
if(recv(sock,buffer,sizeof(buffer),0)==-1){ // recivimos lo que nos envia el cliente
printf("error reciviendo");
exit(0);
}
puts("Esto es lo que envio el cliente;\n");
puts(buffer);
getch();
closesocket(sock); // Cerramos socket
return 0;
}
Ejemplo de cómo interactuar con ftp
Código:
#include <conio.h>
#include <stdio.h>
#include <windows.h>
#include <string.h>
#define ip "127.0.0.1" //ip del servidor
char buf[100]; // variable para los comandos que enviamos al servidor
char buffer[102]; // variable para los mensajes de bienvenida
char ftp[60]; // variable para los mensajes que recibimos del servidor
int i;
int puerto=21;
int main()
{
WSADATA wsa;
int sock;//definicion del socket.
struct sockaddr_in direccion; //datos del servidor
WSAStartup(MAKEWORD(2,0),&wsa);
if((sock=socket(AF_INET,SOCK_STREAM,0))<0 ){ // creamos socket
printf("problema al crear el socket");
getch();
exit(0);
}
else{
direccion.sin_family=AF_INET;
direccion.sin_port=htons(puerto);
direccion.sin_addr.s_addr=inet_addr(ip);
if(connect(sock,(struct sockaddr*)&direccion,sizeof(direccion))<0){
printf("error al conectar");
getch();
exit(0);
}
for(i=1; i<=3; i++){ // recive 3 mensajes de bienvenida, maximo
if(recv(sock,buffer,sizeof(buffer),0)==-1){
printf("Error recibiendo msg, saliendo…");
exit(0);
}
printf("%s",buffer);
memset(buffer,0,sizeof(buffer));
}
printf("\n\n");
while(!strstr(ftp,"230 Logged on")){ // en cuanto no logeamos el cliente sale
memset(buf,0,sizeof(buf)); // borra la variable
memset(ftp,0,sizeof(ftp));
printf("Comandos protocolo ftp:");
gets(buf);
if(send(sock,buf,sizeof(buf),0)==-1){
printf("error enviando");
exit(0);
}
if(recv(sock,ftp,sizeof(ftp),0)==-1){
printf("Error recibiendo");
exit(0);
}
printf("\n");
printf("Respuesta del servidor\n");
printf("%s\n",ftp);
}
}
return 0;
}
Notas finales:
Link para descargar el Tuto:Link de descarga tuto AQUI
Plataforma utilizada, Borland 6
Server de pruebas ftp FileZilla Server 0.9.37
Agradecimientos a toda la gente que tiene ganas de enseñar y a los que tienen ganas de aprender.
Recuerda, el que lucha puede perder o puede ganar, pero el que no lucha tiene la derrota asegurada.
Marcadores