Duda con sockets C

Iniciado por SARGE553413, 17 Julio 2013, 02:55 AM

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

SARGE553413

Hola a todos.

Estoy aprendiendo a usar sockets en C. (UNIX)

Ya he conseguido hacer un servidor concurrente sin fijarme en ningún ejemplo pero me ha surgido un problema:

Para hacerlo concurrente uso fork(), tengo configurado el server para que lea datos del cliente hasta que éste le envíe un '-1'. Cuando los recive los saca por pantalla y los reenvia. Hasta aquí todo bien, pero el problema es que si finalizo el cliente en lugar de con un '-1' con "ctrl+c", el server entra en bucle infinito, no para de escribir el último mensaje que recibió del cliente.

Por ello he buscado formas de comprobar el estado de un socket, he encontrado la función select(), pero por lo que entiendo ésta comprueba el estado de los descriptores desde el 0 hasta el que le indiquemos menos uno. Yo necesito algún método que permita comprobar el estado de un solo descriptor.
¿Cómo puedo hacerlo?

Muchas gracias.

PD. No subo el código porque es bastante largo, si hace falta decidme y lo subo, o decidme como poner un spoiler que no sé xDD.

eferion

deberías detectar cuando un cliente se va... por ejemplo con un timeout... y en ese caso eliminar al cliente de la lista.

La mecánica para saber si un cliente sigue conectado o no varía en función de si usas TCP o UDP...

Por ejemplo te recomendaría es que los puertos los abrieses en el servidor como no bloqueantes y verificases antes de leer si el cliente ha enviado datos nuevos o no... en caso de no enviar datos nuevos y si salta el timeout borras la conexión.

Pero esto es así por encima... sin conocer el código es complicado dar más detalles.

0xDani

La función select() te permite comprobar cualquier descriptor y/o conjunto de descriptores. Vuelve a mirar la documentación de la función.
I keep searching for something that I never seem to find, but maybe I won't, because I left it all behind!

I code for $$$
Hago trabajos en C/C++
Contactar por PM

SARGE553413

#3
Gracias por las respuestas, lo intentaré con select().

No entiendo como verificarlo con un timeout, subo el código del server: (TCP)


int main(int argc, char **argv)
{
const int PORT=1234;
const int BACKLOG=256;
const int INET_ADDRLEN=256;
const int BUFFER_SIZE=256;

int fd,fd2,rec_size,pr;
unsigned int sin_size=sizeof(sockaddr_in);
char buffer[BUFFER_SIZE];
sockaddr_in server,client;
char ip_handled[INET_ADDRLEN];

if((fd=socket(AF_INET,SOCK_STREAM,0))==-1){
exit(-1);
}

server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr.s_addr=INADDR_ANY;
for(int i=0;i<8;i++) server.sin_zero[i]=0;

if((bind(fd,(sockaddr *)&server,sizeof(sockaddr_in)))==-1){
exit(-1);
}

if((listen(fd,BACKLOG))==-1){
exit(-1);
}
while(1){
printf("Listening...\n");
if((fd2=accept(fd,(sockaddr *)&client,&sin_size))==-1){
printf("Error en accept()\n");
close(fd);
exit(-1);
}else{
pr=fork();
switch(pr){
case -1:
cout<<"Critical Error"<<endl;
close(fd);
close(fd2);
exit(-1);
break;
case 0:
printf("Client lstened \n");
if(inet_ntop(AF_INET,&(client.sin_addr),ip_handled,INET_ADDRLEN)==NULL){
printf("Error en inet_ntop()\n");
close(fd);
close(fd2);
exit(-1);
}else{
printf("Handling client %s at port %d\n",ip_handled,ntohs(client.sin_port));
}
if((rec_size=recv(fd2,buffer,BUFFER_SIZE,0))==-1){
printf("Error en lectura\n");
close(fd);
close(fd2);
exit(-1);
}
while(strcmp(buffer,"-1")!=0){
printf("Mensaje recivido: \n\t%s\n",buffer);
if(send(fd2,buffer,rec_size,0)==-1){
printf("Error en escritura\n");
}
if((rec_size=recv(fd2,buffer,BUFFER_SIZE,0))==-1){
printf("Error en lectura\n");
close(fd);
close(fd2);
exit(-1);
}
}
exit(0);
break;
default:
break;
}
}
}
exit(0);
}