problema con la funcion select();

Iniciado por kondrag_X1, 27 Julio 2010, 20:14 PM

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

kondrag_X1

Buenas pues estaba intentando aclararme con la funcion select y ya de paso terminar una practica para la uni asi qe me puse ha hacer un suministrador de numeros aleatorios qe cuando presiones el teclado sin introducir ningun caracter acabe el programa y qe me puedan desconectar remotamente.

bueno pues el problema que tengo es el siguiente la funcion select siempre me devuelve uno cuando lo qe me interesa esqe sea 0 para que salte el timeout de la funcion select.

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <getopt.h>

#define Puerto 4000
#define N 256
#define STDIN 0

//declaro prototipos
int generador ();

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

int sockfd,connfd,opc=0,maxfd,ret_select,aleatorio;
struct sockaddr_in servidor;
socklen_t size_server;
char buffer[N];
char ip[20];
char suministrador[15]="suministrador\0";
char valor[2]="s:";
struct timeval tv;
fd_set allset,rset;

//comprobamos los argunmentos qe nos pasan en argc
if(argc!=3){
printf("¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ Error !!!!!!!!!!!!!\n");
printf("Los argumentos pasados no son los correctos.\n");
printf("Uso: nombre_programa -opciones [ argumentos ...]\n");
printf("Salimos del programa.......\n");
exit(1);}

//comprobaremos las opciones que nos han pasado por los comandos
while(opc!=-1){

opc=getopt(argc,argv,valor);

switch(opc){

case 's':
bzero(ip,sizeof(ip));
strcpy(ip,optarg);
break;
}
}

sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd<0){printf("Error en el socket\n");exit(1);}

//inicializamos la structura del servidor(manejador de eventos)
bzero(&servidor,sizeof(servidor));
servidor.sin_family=AF_INET;
servidor.sin_port=htons(Puerto);
servidor.sin_addr.s_addr=inet_addr(ip);


size_server=sizeof(servidor);

connfd=connect(sockfd,(struct sockaddr*)&servidor,size_server);
if(connfd<0){printf("Error en el connect\n");exit(1);}


printf("\n>>>>>>>>SUMINISTRADOR<<<\n");
printf("\n#Conectado con el servidor:%s por el puerto %d\n\n",ip,Puerto);

//enviamos el mensaje suministrador para registranos en el manejador de eventos
write(sockfd,suministrador,sizeof(suministrador));
printf(">>>>>>DIGO :%s\n",suministrador);

//inicializamos los conjuntos de descriptores
FD_ZERO(&rset);
FD_ZERO(&allset);

//añadimos el conjunto de descriptores a observar teclado y el canal de comunicaciones
FD_SET (STDIN,&allset);
FD_SET (sockfd,&allset);

//colocamos el descriptor como el maximo
maxfd=sockfd;

//generamos el primer tiempo de espera con un numero aleatorio y lo guardamos en la structura
aleatorio=tv.tv_sec=generador();
tv.tv_usec=0;

while(1){

//igualamos el conjunto general con el auxiliar
rset=allset;

printf("vamos a esperar %d para enviar el mensaje\n",aleatorio);

ret_select=select(maxfd+1,&rset,NULL,NULL,&tv);
// printf("\n\tret_select=%d\n",ret_select);

//comprovaremos que descriptores an saltado o si ha sido el tiempo
//salta el socket
if(FD_ISSET(sockfd,&rset)==1){
// printf("\n\tsoy yo el qe salta\n\t");
//si recibimos un caracter en blanco qe cierro la conexcion
bzero(buffer,sizeof(buffer));
read(sockfd,buffer,sizeof(buffer));

if(strlen(buffer)==1){
printf("\n>>>>> nos desconectan...\n\t Adios\n");
close (sockfd);
exit(1);
}
}

   //salta el teclado
   if(FD_ISSET(STDIN,&rset)==1){

bzero(buffer,sizeof(buffer));
fgets(buffer,sizeof(buffer),stdin);
if(strlen(buffer)==1){
printf("\n>>>>> nos desconectamos...\n\t Adios\n");
close (sockfd);
exit(1);
}
}

//salta el timeoout
if(ret_select==0){printf("warning");}
}

close(sockfd);
return 0;
}

int generador(){
//generamos la semilla con el numero de proceso
srand(time(NULL));
//genera el numero aleatorio que ira de 0-10
return rand()%11;
}



Lh: No hagas doble post, utiliza el botón modificar.

haber e estado dandole vueltas al tema y creo qe el fallo esta en el servidor para hacer las pruebas adjunto codigo para ver si a alguien se le enciendo la bonbilla por qe la mia esta ya fundida.

//      server.c
//      DE PRUEBA



#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <getopt.h>

#define N 256

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

int sockfd,bindfd,connfd;
socklen_t size_cliente;
char buffer[N];
struct sockaddr_in servidor,cliente;


//descriptor del socket
sockfd=socket(AF_INET,SOCK_STREAM,0);

//inicializamos la structura
bzero(&servidor,sizeof(servidor));
servidor.sin_family=AF_INET;
servidor.sin_port=htons(4000);
servidor.sin_addr.s_addr=htonl( INADDR_ANY );

//guardamos los recursos del sistema
bindfd=bind(sockfd,(struct sockaddr*)&servidor,sizeof(servidor));

//capaz de escuchar a la vez

listen(sockfd,5);

size_cliente=sizeof(cliente);

while(1){
connfd=accept(sockfd,(struct sockaddr *)&cliente,&size_cliente);

read(connfd,buffer,256);
printf("%s\n",buffer);
close(connfd);
}

close(sockfd);
return 0;
}

AnKeR


Te salta el evento de lectura en el socket porque tiene que saltar. Me explico.

Para saber si un socket está cerrado, salta un evento de lectura, y al hacer un read se lee una longitud 0. De esta manera podemos saber si el otro extremo de la comunicación ha cerrrado el socket.

En el código del servidor se puede ver cómo cierras el socket nada más hacer un printf, por lo que en el cliente salta el evento de lectura para avisar que está cerrado.

Luego también esté el problema de que la comprobación del cierre del socket está mal, debería de ser 0, no uno O_o y también no tienes pq hacer un strlen del buffer ni un bzero, ya que read este dato (bytes leídos) ya te lo devuelve el read.

kondrag_X1

ok muchas gracias por la respuesta la verdad esqe me a servido de mucha ayuda el code no ta terminado y gracias por el consejo no cai en qe read te devolvia los bytes leidos , encuanto lo de 0 en vezde uno no tengo muy claro a lo qe te refieres si es

if(FD_ISSET(sockfd,&rset)==1)

segun lo que pude entender esta funcion "FD_SET()" te devuelve 1 si salta el descriptor y 0 cuando no salta.

AnKeR

No, lo del FD_ISSET, está bien, lo que está mal es la condición de detección de que se han desconectado desde el otro extremo de la conexión:

Citar
               if(strlen(buffer)==1){
                     printf("\n>>>>> nos desconectan...\n\t Adios\n");


Como te expliqué en el post anterior, cuando se cierra el socket desde el otro extremo, el tamaño de lo leído por read es 0, no 1.
Si te fijas estás cerrando todo el rato el socket desde el server (haces un close después de un read en el server), y como esta condición está mal se queda en el bucle, prueba a cambiar ese 1 por un 0.

Y ahora ya una cosa personal, por favor, si yo te respondo sin faltas de ortografía agradecería que me respondieras sin ellas. Un saludo.

kondrag_X1

ok ,muchas gracias y perdona si te he ofendido con mi forma de escribir