Problemita con sockets

Iniciado por pacosn1111, 19 Mayo 2016, 00:20 AM

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

pacosn1111

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.

AlbertoBSD

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..
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

pacosn1111

Cita de: 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..

La parte del recv es esta:


while(1){
if(numbytes=recv(fd,buf,100,0)==-1) printf("error recv");

   buf[numbytes]='\0';
   printf("%s", buf);
   
   }

ivancea96

Coloca paréntesis:
Código (cpp) [Seleccionar]
if((numbytes=recv(fd,buf,100,0))==-1)

pacosn1111

Cita de: ivancea96 en 19 Mayo 2016, 13:47 PM
Coloca paréntesis:
Código (cpp) [Seleccionar]
if((numbytes=recv(fd,buf,100,0))==-1)

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

AlbertoBSD


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
client = fdopen(c, "w")

a una estructura tipo FILE.

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

saludos

Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

ivancea96

Cita de: pacosn1111 en 19 Mayo 2016, 14:13 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?

AlbertoBSD

#7
Que protocolo es?

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.

If the connection or binding succeeds, zero is returned. On error, -1 is returned, and errno is set appropriately.
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

pacosn1111

Gracias por vuestras respuestas, estoy ya hecho un lio, os pongo los sources:

Esta es la librería ss.c:


#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> 
#include <arpa/inet.h>
#include <unistd.h>
#include <strings.h>
#include "ss.h"
/* El número máximo de datos en bytes */

int fd, fd_client, fd_server;

int client(char ip[25], int port)
{

   /* ficheros descriptores */

   char buf[MAXDATASIZE]; 
   /* en donde es almacenará el texto recibido */

   struct hostent *he;         
   /* estructura que recibirá información sobre el nodo remoto */

   struct sockaddr_in server; 
   /* información sobre la dirección del servidor */

   if ((he=gethostbyname(ip))==NULL){       
      /* llamada a gethostbyname() */
      printf("gethostbyname() error\n");
      return(1);
   }

   if ((fd=socket(AF_INET, SOCK_STREAM, 0))==-1){ 
      /* llamada a socket() */
      printf("socket() error\n");
      return(1);
   }

   server.sin_family = AF_INET;
   server.sin_port = htons(port);
   /* htons() es necesaria nuevamente ;-o */
   server.sin_addr = *((struct in_addr *)he->h_addr); 
   /*he->h_addr pasa la información de ``*he'' a "h_addr" */
   bzero(&(server.sin_zero),8);

   if(connect(fd, (struct sockaddr *)&server,
      sizeof(struct sockaddr))==-1){
      /* llamada a connect() */
      printf("connect() error\n");
      return(1);
   }
   return(0);

}

int server(int port) {

   struct sockaddr_in server;
   /* para la información de la dirección del servidor */

   struct sockaddr_in client;
   /* para la información de la dirección del cliente */

   int sin_size;

/* A continuación la llamada a socket() */
   if ((fd_server=socket(AF_INET, SOCK_STREAM, 0)) == -1 ) { 
      printf("error en socket()\n");
      return(1);
   }

   server.sin_family = AF_INET;         

   server.sin_port = htons(port);

   server.sin_addr.s_addr = INADDR_ANY;
   /* INADDR_ANY coloca nuestra dirección IP automáticamente */

   bzero(&(server.sin_zero),8);
   /* escribimos ceros en el reto de la estructura */


   /* A continuación la llamada a bind() */
   if(bind(fd_server,(struct sockaddr*)&server,
           sizeof(struct sockaddr))==-1) {
      printf("error en bind() \n");
      return(1);
   }     

   if(listen(fd_server,2) == -1) {  /* llamada a listen() */
      printf("error en listen()\n");
      return(1);
   }

   sin_size=sizeof(struct sockaddr_in);
      /* A continuación la llamada a accept() */
      if ((fd_client = accept(fd_server,(struct sockaddr *)&client,
                        &sin_size))==-1) {
         printf("error en accept()\n");
        return(1);
      }
      return(0);
  }


Estos sus headers en un fichero .h:


#define MAXDATASIZE 100
extern int fd;
extern int fd_client;
extern int fd_server;   
int client(char[], int);
int server(int);


Este es el server:


#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> 
#include <arpa/inet.h>
#include <unistd.h>
#include <strings.h>
#include "ss.h"

int fd_client;
int fd_server;

void main() {

if((server(3550))==1) printf("hubo un fallo abriendo el socket");

while(1) send(fd_client, "hola", 100, 0);

close(fd_client);
}


Y este el cliente:


#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> 
#include <arpa/inet.h>
#include <unistd.h>
#include <strings.h>
#include "ss.h"

void main() {

int fd;
char buf[100];
int numbytes;

if((client("localhost", 3550))==1) printf("hubo un fallo abriendo el socket");
while(1){
    if((numbytes=recv(fd,buf,100,0))==-1) printf("error recv");

   buf[numbytes]='\0';
   printf("%s", buf);
   
   }
close(fd);
}


Saludos.

ivancea96

Como detalle:
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.