Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: pacosn1111 en 19 Mayo 2016, 00:20 am



Título: Problemita con sockets
Publicado por: pacosn1111 en 19 Mayo 2016, 00:20 am
Estoy haciendo una pequeña libreria para sockets en C muy simple, basicamente es un fichero .c con dos funciones una para servidor y otra para cliente, en un .h meto los descriptores de los sockets exportandolos con extern y he creado dos archivos .c para probar la biblioteca, uno para el server y otro para el client, llegan a conectarse por un socket pero el recv me da error -1 y no se que puede ser. No he pegado el codigo por que es un poco largo.

Saludos.


Título: Re: Problemita con sockets
Publicado por: AlbertoBSD en 19 Mayo 2016, 01:35 am
Posiblemente el socket ae cerro por algun error o no le estas pasando los parametros correctos.

No es necesario que pegues todo el codigo solo la linea involucrada y sus variables..


Título: Re: Problemita con sockets
Publicado por: pacosn1111 en 19 Mayo 2016, 12:34 pm
Posiblemente el socket ae cerro por algun error o no le estas pasando los parametros correctos.

No es necesario que pegues todo el codigo solo la linea involucrada y sus variables..

La parte del recv es esta:

Código
  1. while(1){
  2. if(numbytes=recv(fd,buf,100,0)==-1) printf("error recv");
  3.  
  4.   buf[numbytes]='\0';
  5.   printf("%s", buf);
  6.  
  7.   }
  8.  


Título: Re: Problemita con sockets
Publicado por: ivancea96 en 19 Mayo 2016, 13:47 pm
Coloca paréntesis:
Código
  1. if((numbytes=recv(fd,buf,100,0))==-1)


Título: Re: Problemita con sockets
Publicado por: pacosn1111 en 19 Mayo 2016, 14:13 pm
Coloca paréntesis:
Código
  1. if((numbytes=recv(fd,buf,100,0))==-1)

Gracias, pero lo he probado y sigue dando el mismo error.


Título: Re: Problemita con sockets
Publicado por: AlbertoBSD en 19 Mayo 2016, 14:42 pm

Para leer desde sockets he aprendido mucho del manual de desarrollador de freebsd.

https://www.freebsd.org/doc/en_US.ISO8859-1/books/developers-handbook/sockets-essential-functions.html

Ahi encuentas un cliente y servidor datetime...

asi mismo algunas llamadas pueden ser distintas en Linux.

En lo personal prefiero migrar el file descriptor con fdopen
Código
  1. client = fdopen(c, "w")

a una estructura tipo FILE.

y usar fwrite para escribir sobre ella o fread para leer desde ella.

saludos



Título: Re: Problemita con sockets
Publicado por: ivancea96 en 19 Mayo 2016, 14:45 pm
Gracias, pero lo he probado y sigue dando el mismo error.

En ese caso, hay un punto en el que el socket deja de funcionarte. Y puede ser, o porque el servidor cerró la conexión, o por problemas al abrirla. ¿Hay algún punto en el que funcione la entrada/salida del socket?


Título: Re: Problemita con sockets
Publicado por: AlbertoBSD en 19 Mayo 2016, 14:48 pm
Que protocolo es?

Código:
The recv() call is normally used only on a connected socket (see)    connect(2)).

Si llamaste a connect antes?

Tienes que validar el resultado de connect antes de llamar a recv. Para el resultado de connect.

Código:
If the connection or binding succeeds, zero is returned. On error, -1 is returned, and errno is set appropriately.


Título: Re: Problemita con sockets
Publicado por: pacosn1111 en 19 Mayo 2016, 15:14 pm
Gracias por vuestras respuestas, estoy ya hecho un lio, os pongo los sources:

Esta es la librería ss.c:

Código
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <sys/types.h>
  4. #include <sys/socket.h>
  5. #include <netinet/in.h>
  6. #include <netdb.h>  
  7. #include <arpa/inet.h>
  8. #include <unistd.h>
  9. #include <strings.h>
  10. #include "ss.h"
  11. /* El número máximo de datos en bytes */
  12.  
  13. int fd, fd_client, fd_server;
  14.  
  15. int client(char ip[25], int port)
  16. {
  17.  
  18.   /* ficheros descriptores */
  19.  
  20.   char buf[MAXDATASIZE];  
  21.   /* en donde es almacenará el texto recibido */
  22.  
  23.   struct hostent *he;        
  24.   /* estructura que recibirá información sobre el nodo remoto */
  25.  
  26.   struct sockaddr_in server;  
  27.   /* información sobre la dirección del servidor */
  28.  
  29.   if ((he=gethostbyname(ip))==NULL){      
  30.      /* llamada a gethostbyname() */
  31.      printf("gethostbyname() error\n");
  32.      return(1);
  33.   }
  34.  
  35.   if ((fd=socket(AF_INET, SOCK_STREAM, 0))==-1){  
  36.      /* llamada a socket() */
  37.      printf("socket() error\n");
  38.      return(1);
  39.   }
  40.  
  41.   server.sin_family = AF_INET;
  42.   server.sin_port = htons(port);
  43.   /* htons() es necesaria nuevamente ;-o */
  44.   server.sin_addr = *((struct in_addr *)he->h_addr);  
  45.   /*he->h_addr pasa la información de ``*he'' a "h_addr" */
  46.   bzero(&(server.sin_zero),8);
  47.  
  48.   if(connect(fd, (struct sockaddr *)&server,
  49.      sizeof(struct sockaddr))==-1){
  50.      /* llamada a connect() */
  51.      printf("connect() error\n");
  52.      return(1);
  53.   }
  54.   return(0);
  55.  
  56. }
  57.  
  58. int server(int port) {
  59.  
  60.   struct sockaddr_in server;
  61.   /* para la información de la dirección del servidor */
  62.  
  63.   struct sockaddr_in client;
  64.   /* para la información de la dirección del cliente */
  65.  
  66.   int sin_size;
  67.  
  68. /* A continuación la llamada a socket() */
  69.   if ((fd_server=socket(AF_INET, SOCK_STREAM, 0)) == -1 ) {  
  70.      printf("error en socket()\n");
  71.      return(1);
  72.   }
  73.  
  74.   server.sin_family = AF_INET;        
  75.  
  76.   server.sin_port = htons(port);
  77.  
  78.   server.sin_addr.s_addr = INADDR_ANY;
  79.   /* INADDR_ANY coloca nuestra dirección IP automáticamente */
  80.  
  81.   bzero(&(server.sin_zero),8);
  82.   /* escribimos ceros en el reto de la estructura */
  83.  
  84.  
  85.   /* A continuación la llamada a bind() */
  86.   if(bind(fd_server,(struct sockaddr*)&server,
  87.           sizeof(struct sockaddr))==-1) {
  88.      printf("error en bind() \n");
  89.      return(1);
  90.   }    
  91.  
  92.   if(listen(fd_server,2) == -1) {  /* llamada a listen() */
  93.      printf("error en listen()\n");
  94.      return(1);
  95.   }
  96.  
  97.   sin_size=sizeof(struct sockaddr_in);
  98.      /* A continuación la llamada a accept() */
  99.      if ((fd_client = accept(fd_server,(struct sockaddr *)&client,
  100.                        &sin_size))==-1) {
  101.         printf("error en accept()\n");
  102.        return(1);
  103.      }
  104.      return(0);
  105.  }
  106.  

Estos sus headers en un fichero .h:

Código
  1. #define MAXDATASIZE 100
  2. extern int fd;
  3. extern int fd_client;
  4. extern int fd_server;  
  5. int client(char[], int);
  6. int server(int);
  7.  

Este es el server:

Código
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <sys/types.h>
  4. #include <sys/socket.h>
  5. #include <netinet/in.h>
  6. #include <netdb.h>  
  7. #include <arpa/inet.h>
  8. #include <unistd.h>
  9. #include <strings.h>
  10. #include "ss.h"
  11.  
  12. int fd_client;
  13. int fd_server;
  14.  
  15. void main() {
  16.  
  17. if((server(3550))==1) printf("hubo un fallo abriendo el socket");
  18.  
  19. while(1) send(fd_client, "hola", 100, 0);
  20.  
  21. close(fd_client);
  22. }
  23.  

Y este el cliente:

Código
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <sys/types.h>
  4. #include <sys/socket.h>
  5. #include <netinet/in.h>
  6. #include <netdb.h>  
  7. #include <arpa/inet.h>
  8. #include <unistd.h>
  9. #include <strings.h>
  10. #include "ss.h"
  11.  
  12. void main() {
  13.  
  14. int fd;
  15. char buf[100];
  16. int numbytes;
  17.  
  18. if((client("localhost", 3550))==1) printf("hubo un fallo abriendo el socket");
  19. while(1){
  20.    if((numbytes=recv(fd,buf,100,0))==-1) printf("error recv");
  21.  
  22.   buf[numbytes]='\0';
  23.   printf("%s", buf);
  24.  
  25.   }
  26. close(fd);
  27. }
  28.  

Saludos.


Título: Re: Problemita con sockets
Publicado por: ivancea96 en 19 Mayo 2016, 15:38 pm
Como detalle:
Código
  1. while(1) send(fd_client, "hola", 100, 0);
El tercer argumento es el tamaño de la cadena. En este caso, debería ser 4, o 5 si quieres enviar el caracter nulo.

A parte de eso: en el header declaras fd, fd_client y fs_server, como extern. En los main, debes usar esas variables. No tienes que declararlas de nuevo: ya están declaradas en ss.c. Quita las declaraciones de esas variables en los main, y prueba de nuevo.


Título: Re: Problemita con sockets
Publicado por: pacosn1111 en 19 Mayo 2016, 15:46 pm
Como detalle:
Código
  1. while(1) send(fd_client, "hola", 100, 0);
El tercer argumento es el tamaño de la cadena. En este caso, debería ser 4, o 5 si quieres enviar el caracter nulo.

A parte de eso: en el header declaras fd, fd_client y fs_server, como extern. En los main, debes usar esas variables. No tienes que declararlas de nuevo: ya están declaradas en ss.c. Quita las declaraciones de esas variables en los main, y prueba de nuevo.

Ostras, ya funciona, muchas gracias, pero es que yo tenía entendido que cuando tu declaras una variable en un header como extern, sólo estás diciendo que esa variable va a ser compartida, y que por ende hay que declararlo en cada fichero que se use.


Título: Re: Problemita con sockets
Publicado por: ivancea96 en 19 Mayo 2016, 16:07 pm
Una variable extern significa que existe, pero está en otro lugar. Si declaras una variable extern y luego no la declaras de forma normal, verás que te da una "undefined reference" al enlazar. Es porque no encuentra su declaración.


Título: Re: Problemita con sockets
Publicado por: pacosn1111 en 19 Mayo 2016, 16:18 pm
Una variable extern significa que existe, pero está en otro lugar. Si declaras una variable extern y luego no la declaras de forma normal, verás que te da una "undefined reference" al enlazar. Es porque no encuentra su declaración.

Por eso mismo, lo que he hecho es quitar la declaración de servidor.c y cliente.c, ¿Por que no da error?, es que en otro code que tengo, mucho más complejo, la declaración tengo que hacerla tanto en la biblioteca como en el resto de ficheros, sino me da ese error.


Título: Re: Problemita con sockets
Publicado por: ivancea96 en 19 Mayo 2016, 16:22 pm
No da error porque es correcto. Tal vez en el otro proyecto no enlazaste el código objeto de la librería, no sé.