2010-08-16 33 views
2

Ma question est similaire à ce post. Mais je n'envoie pas de longueur de paquet plutôt un 0 octet à la fin. Donc, je me demande comment je pourrais coder quelque chose qui le ferait.Comment lire le flux java jusqu'à ce qu'un certain octet soit atteint

Au moment où je viens d'utiliser

this.socketIn = new BufferedReader(new InputStreamReader(this.socket.getInputStream())); 
String line = this.socketIn.readLine(); 

Si paquet s'envoyé pendant que vous spamming le paquet, il va compter le paquet qui n'a pas encore arrivé comme lu entièrement la ligne, mais il est incomplet et bousille tout le protocole.

Dans mon protocole, chaque paquet est terminé avec un 0 octet (0x00) pour déterminer la fin d'un seul paquet si les paquets finissent par être fusionnés/empilés ensemble. Donc, ce que j'essaie de faire est de continuer à lire le flux socket jusqu'à ce qu'un 0x00 soit atteint pour indiquer que le paquet est entièrement conçu et prêt pour le traitement .. et bien sûr une sorte de sécurité (un timeout est le meilleur croire) pour déterminer le paquet est indésirable car il n'est pas terminé dans un octet 0 dans un laps de temps spécifique laisse dire 5 secondes.

Comment ferais-je cela? Je n'utilise pas le framework NIO mais juste un thread régulier par socket de connexion et je ne veux pas passer à NIO car il est très difficile d'injecter des données avec un thread global complètement différent qui traite les mises à jour et envoie mises à jour spécifiques aux utilisateurs aléatoires (non diffusés).

Voici ce que j'ai essayé jusqu'ici.

String line = ""; 
    int read; 
    long timeOut = System.currentTimeMillis(); 
    while(true) { 
     read = this.socketIn.read(); 
     if (read == -1 || read == 0 || (System.currentTimeMillis()-timeOut) > 5000) 
      break; 
     line += read 
    } 
+1

Quel est le problème avec ce que vous avez essayé jusqu'à présent? BTW utilise Socket.setSoTimeout(), ne développe pas le vôtre. – EJP

+0

Haha remercie EJP je ne savais pas qu'une commande tmeout existait. – SSpoke

Répondre

5

Voici une esquisse à l'aide setSocketTimeout pour traiter le scénario « client lent/déni de service ».

this.socket.setSoTimeout(5000); 
BufferedReader br = new BufferedReader(
    new InputStreamReader(this.socket.getInputStream())); 
StringBuilder sb = new StringBuilder(); 
try { 
    int ch ; 
    while ((ch == br.read()) != -1) { 
     if (ch == 0) { 
      String message = sb.toString(); 
      // process message 
      sb.setLength(0); 
     } else { 
      sb.append((char) ch); 
     } 
    } 
} catch (InterruptedIOException ex) { 
    System.err.println("timeout!"); 
    ... 
} finally { 
    br.close(); 
} 

je pense qu'il est également possible de mettre en oeuvre une temporisation de douille (brutal) en créant un second thread qui appelle socket.close() sur l'objet de la prise si elle détecte que le fil de lecture ne reçoit pas de données. Mais c'est une approche lourde, étant donné l'approche plus simple setSoTimeout().

+0

k après la recherche, j'ai découvert que StringBuffer est plus rapide que la concaténation d'objets régulière et StringBuilder que vous avez utilisé est encore plus rapide. Aussi plus de recherche trouvé il n'y a pas de commande .clear() donc je suppose que vous utilisez une interface différente mais vu que vous ne l'avez jamais vraiment compilé vous avez fait une erreur je suppose .. Mais j'ai trouvé une solution je suppose que je suis en utilisant votre méthode pour effacer vous utilisez simplement sb.setLength (0); correct? – SSpoke

+0

@SSpoke - mon erreur ... corrigée. C'est pourquoi j'ai appelé le code un "sketch". –

0

Devrais-je utiliser StringBuilder? ou construire le mien comme EJP a écrit. lequel est plus vite?

  String line = ""; 
      int read; 
      //long timeOut = System.currentTimeMillis(); 
      this.socket.setSoTimeout(5000); 
      while(this.socket.isConnected()) { 
      read = this.socketIn.read(); 
      if (read == -1) 
       throw new IOException("Insufficient data/timeout)"); 
      else if(read == 0) 
       break; 
      line += (char)(read & 0xFF); 
      } 
2
InputStreamReader isr = new InputStreamReader(socket.getInputStream()); 
BufferedReader in = new BufferedReader(isr); 
String line = ""; 
String response = ""; 
while ((line = in.readLine()) != null) { 
    System.out.println(line); 
    response = response + line + "\n"; 
    if (in.ready() == false) { 
     break; 
    } 
} 

L'astuce est la fonction prêt qui appartient à la BufferedReader. Vous devez vérifier si c'est prêt, sinon sortir de la boucle.