• Viernes 19 de Abril de 2024, 01:18

Autor Tema:  select en sockets non-blocking  (Leído 1402 veces)

diego.martinez

  • Miembro MUY activo
  • ***
  • Mensajes: 297
    • Ver Perfil
select en sockets non-blocking
« en: Lunes 12 de Enero de 2009, 10:49 »
0
Buenas:

estoy haciendo una comunicación UDP entre 2 equipos. Cuando se produce un evento, el equipo A manda una trama UDP al equipo B que esta en escucha con Bind.

Uso select para ver si tengo que hacer recv en el recepctor. Y aqui viene el problema, el receptor a pesar de tener un sleep , me consume el 98% de la CPU. Alguien sabe que hago mal?

Os pongo el codigo.
Código: Text
  1.    
  2. //este es el bucle de mensajeria de windows
  3.  
  4. while (!this->IsFinished() && !this->IsRestarting())
  5.     {
  6.         this->Messager(); //translate message, dispatch etc...
  7.  
  8.         this->UDPServer->Poll();
  9.  
  10.         Sleep(this->Main_Sleep); //vale 1 MainSleep
  11.     }
  12.  
  13.  

y este es el UDPServer
Código: Text
  1.  
  2.  
  3. int appIP::InitHost()
  4. {
  5.         //creamos un socket para UDP
  6.     this->Socket=socket(AF_INET, SOCK_DGRAM, 0);
  7.     if (this->Socket==SOCKET_ERROR) return 1;
  8.  
  9.     //limpiamos nuestra address para hacer de host
  10.     memset((void *)&Host, '', sizeof(struct sockaddr_in));
  11.  
  12.    
  13.     /* Set family and port */
  14.     Host.sin_family = AF_INET;
  15.     Host.sin_port = htons(Port);
  16.  
  17.     /* Get host name of this computer */
  18.         gethostname(host_name, sizeof(host_name));
  19.         HostProperties = gethostbyname(host_name); //cojemos el nombre de la maquina local
  20.  
  21.         /* Check for NULL pointer */
  22.         if (HostProperties == NULL)
  23.             return 1;
  24.  
  25.         /* Assign the address */
  26.         Host.sin_addr.S_un.S_un_b.s_b1 = HostProperties->h_addr_list[0][0];
  27.         Host.sin_addr.S_un.S_un_b.s_b2 = HostProperties->h_addr_list[0][1];
  28.         Host.sin_addr.S_un.S_un_b.s_b3 = HostProperties->h_addr_list[0][2];
  29.         Host.sin_addr.S_un.S_un_b.s_b4 = HostProperties->h_addr_list[0][3];
  30.  
  31.         /*tenemos la ip , hagamosla string*/
  32.         sprintf(StringIP,"%d.%d.%d.%d",Host.sin_addr.S_un.S_un_b.s_b1,Host.sin_addr.S_un.S_un_b.s_b2,Host.sin_addr.S_un.S_un_b.s_b3,Host.sin_addr.S_un.S_un_b.s_b4);
  33.        
  34.         TimeOut.tv_usec = msTimeout%1000;
  35.         TimeOut.tv_sec = msTimeout/1000;  // Time in seconds
  36.  
  37.         FD_ZERO (&fdSocket);
  38.         FD_SET  (Socket, &fdSocket); //ponemos el socket en vigilancia
  39.  
  40.  if (bind(Socket, (struct sockaddr *)&Host, sizeof(struct sockaddr_in)) == -1)
  41.         {
  42.             return 1;
  43.         }
  44.         return 0;
  45. }
  46.  
  47.  
  48.  

Y este es el polling del select.

Código: Text
  1.  
  2. void appIP::Poll()
  3. {
  4.     unsigned int bytes_received=0;
  5.     int AddrSize=(int)sizeof(struct sockaddr_in);
  6.  
  7.     this->fdSocket.fd_count = 1;
  8.  
  9.         if (
  10.             select(0,&this->fdSocket,0,0,&this->TimeOut)  > 0  //hay notificacion
  11.             &&
  12.             FD_ISSET (this->Socket, &this->fdSocket)  //y es nuestro socket
  13.             )
  14.         {
  15.             bytes_received = recvfrom(this->Socket,(char*) this->Buffer, 100, 0, (struct sockaddr *)&this->Ext, &AddrSize);
  16.  
  17.             if (bytes_received>0)
  18.             {
  19.                 if (this->Events["receive"]!=NULL) this->Events["receive"](this);
  20.             }
  21.         }
  22. }
  23.  
  24.  

no se, al select le he puesto un time out de 1 ms para que la mitad del tiempo este durmiendo la cpu, asi que deberia ir relajado. Quizas estoy manejando mal el select?


gracias por anticipado.

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil
Re: select en sockets non-blocking
« Respuesta #1 en: Lunes 12 de Enero de 2009, 10:57 »
0
¿Probaste con 100 en lugar de 1 en ambos (milisegundos)?

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.

diego.martinez

  • Miembro MUY activo
  • ***
  • Mensajes: 297
    • Ver Perfil
Re: select en sockets non-blocking
« Respuesta #2 en: Lunes 12 de Enero de 2009, 12:28 »
0
gracias por la respuesta.

Pues si, lo probé y seguia igual de mal. Al final buscando he encontrado el fallo:

Código: Text
  1.  
  2. u_long iMode = 1;   // <------ el fallo es que no habia entendido bien que parametro se pasaba como iMode.
  3.         ioctlsocket (Socket, FIONBIO, &iMode);
  4.  
  5.  

En la espec pone que iMode debe ser distinto de 0 para que sean non-blocking. Bien la cosa es que se refieren al valor interno, no a la direccion (pensaba que era que si le pasabas null seria blocking) pero hay que poner iMode a 1 para que sean non-blocking de verdad, asi que con eso se solucionó.

Gracias igualmente. Nos vemos.  :hola: