Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème Serveur (sockets)

Sujet résolu
    14 février 2012 à 18:42:49

    Bonjour, je suis entrain de faire un serveur, sur lequel je me connecte avec le shell linux par la commande telnet.
    Ce serveur est censé être une copie de "chargen" qui envoie à l'infinie les 100 caractères ascii affichable.
    Voici le code, ensuite viendrons les problèmes :diable: .


    public static void main(String args[]) throws UnknownHostException, IOException{
    		ServerSocket server;
                   
                    try {
    		     server=new ServerSocket(9876, 10, InetAddress.getLocalHost());
    		     Thread t = new Thread(new Accepter_clients(socket));
    		     t.start();
    		
                    } catch (IOException e) {
    			
    			e.printStackTrace();
    		}
    	}
    


    class Accepter_clients implements Runnable {
    
    	   private ServerSocket socketserver;
    	   private Socket socket;
    	  
    	   public Accepter_clients(ServerSocket s){
    			socketserver = s;
    		}
    		
    		public void run() {
    			
    			PrintWriter out;
    			InputStream in;
    						
    			try {
    	        	while(true){
    			  socket = socketserver.accept(); 
    			  out = new PrintWriter(socket.getOutputStream());
    			  
    			  while(true){
    				  for(int i=32; i<127; i++){
    	           		  out.print((char)i);
             				
    	  	            	   }
    	           		
    	           			out.flush();
    	                    }
    			 
    	       
    	        	}
    	        
    	        } catch (Exception e) {
    	        	
    				e.printStackTrace();
    			}
    		}
    
    	}
    


    Voici mon problème n°1, j'ai mis un thread dans le main, normalement mon serveur peut être accessible par plusieurs shell en même temps, mais non... par contre quand je mets 2 thread, la je peut me connecter 2 fois, 3 thread = 3 fois etc... Je pense que j'ai pas trop compris...

    problème n°2(et le dernier >_< ):

    while(true){
    				  for(int i=32; i<127; i++){
    	           		  out.print((char)i);
             				
    	  	            	   }
    	           		
    	           			out.flush();
    }
    


    Je ne sais pas quoi mettre a la place de ce while(true), pour faire en sorte que je quitte cette boule, au moment ou le client appuie sur (CTRL+ALTGR+]) ce qui le déconnecte du serveur telnet, et donc me permettra de fermer le socket après cette boucle. Ou même si le client a une panne internet ou je ne sais quoi.

    Merci de vos généreuse réponses.
    • Partager sur Facebook
    • Partager sur Twitter
      14 février 2012 à 19:55:53

      Je pense qu'en effet tu n'as pas bien compris le duo client/serveur et Runnable.

      Pour le moment ton main ce contente de créer un thread qui attend une connexion puis affiche ce que tu veux. Pour avoir ce que tu nous décris il faudrait plutôt que tu fasse une boucle infini qui écoute les nouvelles connexion ( soscketserver.accept) dans ton main puis que tu lance un thread pour chacun des clients qui ce sont connecté.

      Pour ton deuxième problème je crois qu'il se résoudra de lui même, il me semble que le thread se fera tuer lorsque le client ce sera déconnecté.
      • Partager sur Facebook
      • Partager sur Twitter
        14 février 2012 à 20:14:26

        merci, pour ta réponse, en effet, mon problème 1 est résolu, mais le 2 persiste, quoi que le client fasse, mon while(true) ne s'arrête pas, mon serveur continue d'envoyer le code ascii a l'infini. Il n'y a pas une méthode genre while(socket.YaQuelqunQuiTecoute()) ?

        import java.io.BufferedReader;
        import java.io.IOException;
        import java.io.InputStream;
        import java.io.InputStreamReader;
        import java.io.PrintWriter;
        import java.net.InetAddress;
        import java.net.ServerSocket;
        import java.net.Socket;
        import java.net.SocketException;
        import java.net.UnknownHostException;
        
        public class ChargenServer {
        
        	public static void main(String args[]) throws UnknownHostException, IOException{
        		ServerSocket server;
                       
                        try {
        		     server=new ServerSocket(9876, 10, InetAddress.getByName("localhost"));
        		    System.out.println(InetAddress.getLocalHost());
        		    System.out.println(InetAddress.getByName("localhost"));
        		    
        		    while(true){
        		    Socket socket=server.accept();
        		    Thread t = new Thread(new Accepter_clients(socket));
        		    t.start();
        		     
        		    
        		    }
                        } catch (IOException e) {
        			
        			e.printStackTrace();
        		}
        	}
        }
        
        class Accepter_clients implements Runnable {
        
        	   
        	   private Socket socket;
        	  
        	   public Accepter_clients(Socket s){
        			socket = s;
        		}
        		
        		public void run() {
        			
        			PrintWriter out;
        			int j=0;
        						
        			try {
        				out = new PrintWriter(socket.getOutputStream());
        	        	while(true){ // here is GROS problème
        			  
        				  for(int i=32; i<127; i++){
        	           		  out.print((char)i);
              				
        	  	            	   }
        	           		System.out.println(j++);
        	           			out.flush();
        	                    }
        			 
        	       
        	        	
        	        
        	        } catch (Exception e) {
        	        	
        				e.printStackTrace();
        			}
        		}
        
        	}
        


        je vois que ma boucle est le problème car après déconnexion du client, le system.out.println(j++) continu.


        Edit:
        Etape 1: je me connecte au serveur, tout se passe normalement, sur eclipse je vois mon j++ qui s'incrémente a fond (au moment de la capture 1917)
        Image utilisateur


        Etape 2: Je pause l'affichage avec CTRL+$ (l'escape character). mon j++ se stoppe sur 3417.
        Image utilisateur

        Etape 3: je fait quit, et la bizarrement mon j++ s'incrémente a fond. c'est ça que je veut éviter... mon serveur envoi des message dans le vide... (le pire c'est qu'il va au moins 20 fois plus vite, y'a le même laps de temps entre chaque photo et il est déja a 70 000.

        Image utilisateur
        • Partager sur Facebook
        • Partager sur Twitter
          15 février 2012 à 15:06:31

          Le test de connexion est réalisée à la lecture (et non à l'écriture).

          Voilà en gros comment faire une lecture.

          InputStream in = socket.getInpoutStream();
          
          while(true) {
          
               int read = 0; // nombre d'octet lu
          
               // buffer final de récéption
               StringBuffer stringBuffer = new StringBuffer();
          
               do {
                    // buffer temporaire
                    byte[] buffer = new byte[256];
          
                    // lecture du flux dans le buffer temporaire
                    // renvois le nombre d'octet lu
                    read = socket.read(byteBuffer);
          
                    // Si un octet a été lu
                    if (read > 0) {
          
                         // buffer à la bonne taille
                         byte[] datas = new byte[read];
          
                         // copie du buffer temporaire dans le buffer de données
                         System.arraycopy(byteBuffer.array(), 0, datas, 0, read);
          
                         // on ajoute les données au buffer final du message
                         stringBuffer .append(new String(datas));
                    }			
          
               // si le buffer temporaire est plein, c'est qu'il reste des octet à lire
               } while (read == 256);
          
               // Si le flux a été fermé
               if (read == -1) {
                    socket.close();
                    throw new IOException("connexion interrompue");
               }
          
               // Si tout est OK, on a notre message
               String message = stringBuffer .toString();
          
          }
          



          Problème, la méthode read(byte[]) est bloquante...

          La solution, c'est de créer un nouveau thread pour chaque client.

          Il y a donc le thread du serveur (qui accepte les nouvelles connexions).
          Et pour chaque client, un thread de lecture (qui détecte aussi la fermeture de connexion), et un thread d'écriture.


          Evidemment, on se retrouve avec n * 2 + 1 thread (où n est le nombre de clients connecté).


          Au delà d'une dizaine de thread, il est préférable d'utiliser les "Selector"(du package java.nio ), qui permettent de n'utiliser qu'un seul et unique thread.

          • Partager sur Facebook
          • Partager sur Twitter
            15 février 2012 à 16:37:42

            Merci pour ta réponse, pour l'instant 10 connexion c'est même pas envisageable :P, je vais faire comme tu as dit, un thread pour l'écriture et un autre pour la lecture, . Il me reste plus qu'a en apprendre plus sur les "Selector". Merci beaucoup, problème résolu.
            • Partager sur Facebook
            • Partager sur Twitter

            Problème Serveur (sockets)

            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
            • Editeur
            • Markdown