elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Introducción a Git (Primera Parte)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  problema con la funcion select();
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: problema con la funcion select();  (Leído 2,821 veces)
kondrag_X1

Desconectado Desconectado

Mensajes: 157


Ver Perfil
problema con la funcion select();
« 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.

Código
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <time.h>
  4. #include <string.h>
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <sys/stat.h>
  8. #include <netinet/in.h>
  9. #include <arpa/inet.h>
  10. #include <unistd.h>
  11. #include <fcntl.h>
  12. #include <getopt.h>
  13.  
  14. #define Puerto 4000
  15. #define N 256
  16. #define STDIN 0
  17.  
  18. //declaro prototipos
  19. int generador ();
  20.  
  21. int main(int argc,char *argv[]){
  22.  
  23. int sockfd,connfd,opc=0,maxfd,ret_select,aleatorio;
  24. struct sockaddr_in servidor;
  25. socklen_t size_server;
  26. char buffer[N];
  27. char ip[20];
  28. char suministrador[15]="suministrador\0";
  29. char valor[2]="s:";
  30. struct timeval tv;
  31. fd_set allset,rset;
  32.  
  33. //comprobamos los argunmentos qe nos pasan en argc
  34. if(argc!=3){
  35. printf("¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ Error !!!!!!!!!!!!!\n");
  36. printf("Los argumentos pasados no son los correctos.\n");
  37. printf("Uso: nombre_programa -opciones [ argumentos ...]\n");
  38. printf("Salimos del programa.......\n");
  39. exit(1);}
  40.  
  41. //comprobaremos las opciones que nos han pasado por los comandos
  42. while(opc!=-1){
  43.  
  44. opc=getopt(argc,argv,valor);
  45.  
  46. switch(opc){
  47.  
  48. case 's':
  49. bzero(ip,sizeof(ip));
  50. strcpy(ip,optarg);
  51. break;
  52. }
  53. }
  54.  
  55. sockfd=socket(AF_INET,SOCK_STREAM,0);
  56. if(sockfd<0){printf("Error en el socket\n");exit(1);}
  57.  
  58. //inicializamos la structura del servidor(manejador de eventos)
  59. bzero(&servidor,sizeof(servidor));
  60. servidor.sin_family=AF_INET;
  61. servidor.sin_port=htons(Puerto);
  62. servidor.sin_addr.s_addr=inet_addr(ip);
  63.  
  64.  
  65. size_server=sizeof(servidor);
  66.  
  67. connfd=connect(sockfd,(struct sockaddr*)&servidor,size_server);
  68. if(connfd<0){printf("Error en el connect\n");exit(1);}
  69.  
  70.  
  71. printf("\n>>>>>>>>SUMINISTRADOR<<<\n");
  72. printf("\n#Conectado con el servidor:%s por el puerto %d\n\n",ip,Puerto);
  73.  
  74. //enviamos el mensaje suministrador para registranos en el manejador de eventos
  75. write(sockfd,suministrador,sizeof(suministrador));
  76. printf(">>>>>>DIGO :%s\n",suministrador);
  77.  
  78. //inicializamos los conjuntos de descriptores
  79. FD_ZERO(&rset);
  80. FD_ZERO(&allset);
  81.  
  82. //añadimos el conjunto de descriptores a observar teclado y el canal de comunicaciones
  83. FD_SET (STDIN,&allset);
  84. FD_SET (sockfd,&allset);
  85.  
  86. //colocamos el descriptor como el maximo
  87. maxfd=sockfd;
  88.  
  89. //generamos el primer tiempo de espera con un numero aleatorio y lo guardamos en la structura
  90. aleatorio=tv.tv_sec=generador();
  91. tv.tv_usec=0;
  92.  
  93. while(1){
  94.  
  95. //igualamos el conjunto general con el auxiliar
  96. rset=allset;
  97.  
  98. printf("vamos a esperar %d para enviar el mensaje\n",aleatorio);
  99.  
  100. ret_select=select(maxfd+1,&rset,NULL,NULL,&tv);
  101. // printf("\n\tret_select=%d\n",ret_select);
  102.  
  103. //comprovaremos que descriptores an saltado o si ha sido el tiempo
  104. //salta el socket
  105. if(FD_ISSET(sockfd,&rset)==1){
  106. // printf("\n\tsoy yo el qe salta\n\t");
  107. //si recibimos un caracter en blanco qe cierro la conexcion
  108. bzero(buffer,sizeof(buffer));
  109. read(sockfd,buffer,sizeof(buffer));
  110.  
  111. if(strlen(buffer)==1){
  112. printf("\n>>>>> nos desconectan...\n\t Adios\n");
  113. close (sockfd);
  114. exit(1);
  115. }
  116. }
  117.  
  118.    //salta el teclado
  119.    if(FD_ISSET(STDIN,&rset)==1){
  120.  
  121. bzero(buffer,sizeof(buffer));
  122. fgets(buffer,sizeof(buffer),stdin);
  123. if(strlen(buffer)==1){
  124. printf("\n>>>>> nos desconectamos...\n\t Adios\n");
  125. close (sockfd);
  126. exit(1);
  127. }
  128. }
  129.  
  130. //salta el timeoout
  131. if(ret_select==0){printf("warning");}
  132. }
  133.  
  134. close(sockfd);
  135. return 0;
  136. }
  137.  
  138. int generador(){
  139. //generamos la semilla con el numero de proceso
  140. srand(time(NULL));
  141. //genera el numero aleatorio que ira de 0-10
  142. return rand()%11;
  143. }


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.

Código
  1. //      server.c
  2. //      DE PRUEBA
  3.  
  4.  
  5.  
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <time.h>
  9. #include <string.h>
  10. #include <sys/types.h>
  11. #include <sys/socket.h>
  12. #include <sys/stat.h>
  13. #include <netinet/in.h>
  14. #include <arpa/inet.h>
  15. #include <unistd.h>
  16. #include <fcntl.h>
  17. #include <getopt.h>
  18.  
  19. #define N 256
  20.  
  21. int main(int argc, char** argv){
  22.  
  23. int sockfd,bindfd,connfd;
  24. socklen_t size_cliente;
  25. char buffer[N];
  26. struct sockaddr_in servidor,cliente;
  27.  
  28.  
  29. //descriptor del socket
  30. sockfd=socket(AF_INET,SOCK_STREAM,0);
  31.  
  32. //inicializamos la structura
  33. bzero(&servidor,sizeof(servidor));
  34. servidor.sin_family=AF_INET;
  35. servidor.sin_port=htons(4000);
  36. servidor.sin_addr.s_addr=htonl( INADDR_ANY );
  37.  
  38. //guardamos los recursos del sistema
  39. bindfd=bind(sockfd,(struct sockaddr*)&servidor,sizeof(servidor));
  40.  
  41. //capaz de escuchar a la vez
  42.  
  43. listen(sockfd,5);
  44.  
  45. size_cliente=sizeof(cliente);
  46.  
  47. while(1){
  48. connfd=accept(sockfd,(struct sockaddr *)&cliente,&size_cliente);
  49.  
  50. read(connfd,buffer,256);
  51. printf("%s\n",buffer);
  52. close(connfd);
  53. }
  54.  
  55. close(sockfd);
  56. return 0;
  57. }
  58.  


« Última modificación: 28 Julio 2010, 16:25 pm por Littlehorse » En línea

AnKeR

Desconectado Desconectado

Mensajes: 125


printk("\n%s\n","Kernel Panic");


Ver Perfil
Re: problema con la funcion select();
« Respuesta #1 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.


En línea

kondrag_X1

Desconectado Desconectado

Mensajes: 157


Ver Perfil
Re: problema con la funcion select();
« Respuesta #2 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

Código
  1. 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.
En línea

AnKeR

Desconectado Desconectado

Mensajes: 125


printk("\n%s\n","Kernel Panic");


Ver Perfil
Re: problema con la funcion select();
« Respuesta #3 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:

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.
En línea

kondrag_X1

Desconectado Desconectado

Mensajes: 157


Ver Perfil
Re: problema con la funcion select();
« Respuesta #4 en: 29 Julio 2010, 14:15 pm »

ok ,muchas gracias y perdona si te he ofendido con mi forma de escribir
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
DUDA FUNCION ALMACENADA Y SELECT
PHP
taos19 2 1,511 Último mensaje 21 Febrero 2014, 16:33 pm
por taos19
Problema con <Select> Wordpress y Chrome
Desarrollo Web
Maurice_Lupin 2 2,381 Último mensaje 2 Febrero 2015, 21:58 pm
por Maurice_Lupin
Usar entrada de función como columna en select
Bases de Datos
user-marcos 3 3,299 Último mensaje 29 Junio 2015, 17:15 pm
por WHK
Problema en ASP.NET Razor Pages Select asp-items
.NET (C#, VB.NET, ASP)
Albpous 1 5,375 Último mensaje 17 Febrero 2024, 16:02 pm
por TickTack
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines