PDA

Ver la versión completa : Tutorial socket en (C)



chewarrior
27-10-2010, 01:46
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;



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:


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:



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:



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:




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:




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:



listen(sock,1)


Vamos por partes:




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:


(sock=accept(sock,0,0));



Vamos por partes:



(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:



buffer[20];
recv(sock,buffer,sizeof(buf),0);



Vamos por partes:


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:


#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




#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


#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 (http://www.mediafire.com/?vwqnl54smb9ak78)

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.

Fruit
27-10-2010, 02:06
Así que todo esto es para Windows dices, ¿no?

hystd
27-10-2010, 02:36
Gracias por el aporte, seguro que a más de uno le viene bien para empezar. Esperemos que sigas trabajando en ello y hagas futuras ampliaciones ;).

Un saludo.

hckr
27-10-2010, 19:43
Muy bueno chewarrior, te digo lo mismo que hystd.

chewarrior
27-10-2010, 19:48
Así que todo esto es para Windows dices, ¿no?


Es para windows porque utilizo las librerias windows.h, y hay que iniciar winsock, por lo demas tambien serviria para linux (incluyendo sus librerias).

Fruit
27-10-2010, 23:03
Muy buen post, sí.

maria12
02-11-2010, 02:47
como envias un mensaje de cliente para cuando corras el servidor te aparesca el mensaje del cliente

gondar_f
02-11-2010, 18:12
buen tuto compañero, mis parabienes.

por cierto, no estarías interesado en colaborar con la ezina haciendo algún texto para el próximo número?

salu2

chewarrior
03-11-2010, 14:19
como envias un mensaje de cliente para cuando corras el servidor te aparesca el mensaje del cliente


No te entindo muy bien explicate mejor por favor, pero segun e entendido lo que quieres es que el cliente envie al servidor como un mensaje de bienvenida, no?¿ bueno pues es muy simple a el cliente le agregas la funcion send con el mensaje ya predeterminado, y al server otra funcion recv

Ejemplo;




char olas[30]="olas de maria12";


if(send(sock,olas,sizeof(olas),0)==-1){ // recivimos lo que nos envia el cliente
printf("error reciviendo");
exit(0);
}


-------------------------------------------------
char olas[30];


if(recv(sock,olas,sizeof(olas),0)==-1){ // recivimos lo bienvenida del cliente
printf("error reciviendo");
exit(0);
}

puts(olas);




Mira esto no creo que sea dificil para alguien que se haya leido el tutorial, tal vez deberias de darle una pasada de nuevo.



por cierto, no estarías interesado en colaborar con la ezina haciendo algún texto para el próximo número?


La verdad es que me encantaria, pero estoy demasiado ocupado con los estudios y mis propios proyectos.