Comunicación mediante sockets RAW (cliente-servidor)

Iniciado por PeKiN, 19 Febrero 2011, 16:55 PM

0 Miembros y 1 Visitante están viendo este tema.

PeKiN

Hola!! Necesito comunicar dos sockets de tipo RAW, uno como cliente y otro como servidor. Teóricamente debe ser algo muy sencillo, pero no doy con mi fallo. Aquí expongo el código que utilizo para el cliente y el servidor:

cliente.c


#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <linux/if_ether.h>

int main (int argc, char *argv[]){

  int sock_cli, longitud, n;
  struct sockaddr_in dir_serv;

  sock_cli = socket (AF_INET, SOCK_RAW, IPPROTO_RAW);
  if (sock_cli < 0){
    printf("Error en la funcion socket() \n");
    exit(1);
  }
  bzero(&dir_serv, sizeof(dir_serv));
  dir_serv.sin_family = AF_INET;
  dir_serv.sin_port=htons(4000);
  dir_serv.sin_addr.s_addr=htonl(INADDR_ANY);

  longitud = sizeof (dir_serv);

  n = sendto(sock_cli, "prueba raw", 256, 0, (struct sockaddr *) &dir_serv, sizeof(dir_serv));
  if (n == -1){
    printf("Error en sendto() \n");
    exit(1);
  }
  printf("Valor de n: %d \n", n);

  close(sock_cli);

  exit(0);


}


Aparentemente, el cliente hace su sendto() correctamente, sin embargo, en el servidor..

servidor.c


#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <unistd.h>
#include <string.h>

int main (int argc, char *argv[]){

  int sock_serv, sock_cli, rbind, n;
  socklen_t longitud;
  struct sockaddr_in dir_serv, cliaddr;
  char buff[256];

  sock_serv = socket (AF_INET, SOCK_RAW, IPPROTO_RAW);
  if (sock_serv < 0){
    printf("Error en la funcion socket() \n");
    exit(1);
  }

  bzero(&dir_serv, sizeof(dir_serv));
  dir_serv.sin_family = AF_INET;
  dir_serv.sin_port=htons(4000);
  dir_serv.sin_addr.s_addr=htonl(INADDR_ANY);

  longitud = sizeof(dir_serv);

  rbind = bind(sock_serv, (struct sockaddr *) &dir_serv, longitud);
  if (rbind == -1){
    printf("Error en la funcion bind() \n");
    exit(1);
  }
  printf("Voy a ejecutar recvfrom() \n");
  n = recvfrom(sock_serv, buff, 256,0,(struct sockaddr *) &cliaddr, &longitud);
  if (n > 0){
    printf("He recibido algo\n");
  }
  printf("Valor de n: %d\n", n);
  close (sock_serv);

exit(1);
}


El programa se queda esperando en recvfrom() algo que nunca le llega.
Aparte de que las pruebas las hago en el propio PC (para que no falle por causas externas), he probado a cambiar la signatura de la función socket por la de UDP, ya que el código serviría "socket (AF_INET, SOCK_DGRAM, 0)" y me he encontrado con que la comunicación se produce correctamente y se recibe en el servidor. Sin embargo en RAW me falla, ¿alguien me echa una mano?

Gracias y saludos!!

Garfield07

Link a RAW sockets


dir_serv.sin_port=htons(4000);
dir_serv.sin_addr.s_addr=htonl(INADDR_ANY);

Mal. Para la IP se usa o 0 o INADDR_ANY solo, que ya están en orden de bytes de red. Igualmente para el server. Y para el cliente añádele tu IP a mano, no como la misma. Si lo corres en tu máquina no pasa nada, pero no es nada recomendable :P Cuando lo hagas entre dos PCs no estará bien. Añádele los argumentos en cinco segundos...

Y en vez de sendto () y recvfrom () usa recv y send. Si te lo han puesto así en la universidad pásame el teléfono del profesor que tengo que hablar con él por complicaros la vida... Te adjunto un tutorial mío sobre sockets. Fue el primero que hice, no seas malo xD
Sockets by Sagrini

Suerte!


* Quiero cambiar el mundo, pero estoy seguro de que no me darían el código fuente.
* No estoy tratando de destruir a Microsoft. Ese será tan solo un efecto colateral no intencionado.
* Si compila esta bien, si arranca es perfecto.

¡Wiki elhacker.net!
Un saludo

PeKiN

Hola Sagrini, primeramente gracias por responder. En cuanto a lo del INADDR_ANY, no sabía que ese comodín te proporcionaba la dirección en orden de bytes de red, en cualquier caso, me lo enseñaron así y he seguido usándolo puesto que funciona y no da ningún tipo de error (ni compilación ni ejecución), pero ya sabiendolo, ahorrare unos cuantos caracteres escribiendo código xd

En cuanto al uso de sendto() y recvfrom() ha sido porque en la mayoría de ejemplos que he encontrado por la red comunicando sockets raw las utilizan (también probé por mi cuenta con read() y write() ). En cuanto a sockets, estoy bastante puesto, tengo todas las asignaturas superadas y se me dan bien (tengo los conceptos claros), el problema surge con los sockets RAW. Creo que el problema en mi código es que el paquete del que envía (en este caso sólo el cliente) ha de tener cabecera IP pero configurada de forma manual, de lo contrario, me parece que no está bien enviado, pero aún debo hacer pruebas con códigos que encontré donde parece que se hace lo que busco..

http://sock-raw.org/papers/sock_raw

Buscando /*** IPPROTO_RAW receiver ***/ llegas al código del receiver y del sender.

Tu tutorial sobre sockets está bien, completillo y bien descrito, enhorabuena!

Saludos!!!