2010-11-09 41 views
3

J'ai un nouveau problème avec mon application Android. Le SocketChannel me dit qu'il isReadable() mais il n'y a rien à lire.SocketChannel déclenche isReadable() mais rien à lire

while(running) 
    { 
     int readyChannels = 0; 
     try { 
      readyChannels = selector.select(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     if(readyChannels == 0) continue; 

     Set<SelectionKey> selectedKeys = selector.selectedKeys(); 
     Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); 

     while(keyIterator.hasNext()) 
     { 
      SelectionKey key1 = keyIterator.next(); 

      if(key1.isReadable()) 
      { 
       publishProgress(1); 
      } 

      else if(key1.isWritable()) 
      { 
       publishProgress(2); 
      } 

      else if(!key1.isValid()) 
      { 
       Log.e("State", "progress error"); 
       publishProgress(3); 
      } 
     } 
    } 

J'appelle les fonctions nécessaires à onProgressUpdate. C'est une application WebSocket donc je dois envoyer et recevoir une poignée de main. Envoyer et recevoir la poignée de main fonctionne avec cette boucle while. D'abord le SelectionKey.isWriteable() et le handshake est envoyé puis le SelectionKey.isReadable() et le handshake est lu. Mais alors SelectionKey.isReadable() est toujours vrai. Maintenant, la fonction de lecture normale (pas la fonction readHandshake) est appelée. Mais il n'y a rien à lire. Voici le code de ma fonction de lecture:

public byte[] read(int nBytes) 
{ 
    Log.e("State", "public byte[] read(int nBytes) start"); 

    byte[] resultData = new byte[1024]; 
    ByteBuffer data = ByteBuffer.wrap(resultData); 
    int remainingBytes = nBytes; 

    while(remainingBytes >= 0) 
    { 
     ByteBuffer buffer = ByteBuffer.allocate(1024); 
     int bytesRead = 0; 
     try { 
      bytesRead = channel.read(buffer); 
     } catch (IOException e) { 
      Log.e("ERROR", "channel read"); 
     } 

     if(bytesRead < 0) 
     { 
      sockState = WebSocketState.WebSocketErrorOccurred; 
     } 

     else 
     { 
      remainingBytes = remainingBytes - bytesRead; 
      data.put(buffer.array(), 0, bytesRead); 
     } 
    } 

    Log.e("State", "public byte[] read(int nBytes) done"); 

    return resultData; 
} 

Maintenant, il est bloqué dans une boucle sans fin. remainingBytes ne reçoit jamais < 0 parce qu'il n'y a rien à lire et bytesRead reste 0.

Ma question est pourquoi isReadable est vrai quand il n'y a rien à lire?

Répondre

2

Si bytesRead < 0, vous devez fermer le canal ou au moins désenregistrer OP_READ. Sinon, vous continuerez à vous remettre OP_READ encore et encore pour vous parler de l'EOS.

Vous ne devez pas allouer votre ByteBuffer une fois par lecture. L'allocation de ByteBuffers est une opération coûteuse. Au moins allouer une fois par entrée à la méthode de lecture. Mieux encore, attribuez-en un par canal lorsque vous l'acceptez. Vous pouvez le conserver en tant que, ou via, la pièce jointe de clé afin de ne pas le perdre, et ainsi il disparaît lorsque vous annulez la clé ou fermez la chaîne.

+0

Ok merci pour votre aide. – Martin

+0

sry pour être naïf, mais comment puis-je annuler l'enregistrement de 'OP_READ'? – Mayank