Título: problema con la funcion select();
Publicado por: kondrag_X1 en 27 Julio 2010, 20:14 pm
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"); //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)); 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)); printf("\n>>>>> nos desconectan...\n\t Adios\n"); close (sockfd); } } //salta el teclado if(FD_ISSET(STDIN,&rset)==1){ bzero(buffer,sizeof(buffer)); fgets(buffer ,sizeof(buffer ),stdin ); printf("\n>>>>> nos desconectamos...\n\t Adios\n"); close (sockfd); } } //salta el timeoout if(ret_select ==0){printf("warning");} } close(sockfd); return 0; } int generador(){ //generamos la semilla con el numero de proceso //genera el numero aleatorio que ira de 0-10 }
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); close(connfd); } close(sockfd); return 0; }
Título: Re: problema con la funcion select();
Publicado por: AnKeR en 28 Julio 2010, 19:30 pm
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.
Título: Re: problema con la funcion select();
Publicado por: kondrag_X1 en 28 Julio 2010, 22:19 pm
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.
Título: Re: problema con la funcion select();
Publicado por: AnKeR en 29 Julio 2010, 09:22 am
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: 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.
Título: Re: problema con la funcion select();
Publicado por: kondrag_X1 en 29 Julio 2010, 14:15 pm
ok ,muchas gracias y perdona si te he ofendido con mi forma de escribir
|