100% auslastung?

darkeye2

Bekanntes Mitglied
Hallo, ich habe ein programm geschrieben, dass einen stream wieterleiten soll, doch das problem ist, es zieht dauerhaft 100% cpu auslastung auf einen root server. Ich weiß immer noch net, woran das liegt.

wichtigster codeausschnitt: (restlicher code wird bei bedarf gepostet
Java:
public void runServer(Shoutcast sev){
		try{
			while(live){
				if(wait){
					Socket client = server.accept();
					ch = new clientHandler(client);
				}
			}
		} catch(IOException e){writeLog("Error[runServer] {003}: "+ e.getMessage(), 1);}
	}
	
	protected class clientHandler extends  Thread{
		protected Socket clientSock;
		
		clientHandler(Socket cl){
			clientSock = cl;
			connection  = true;
			writeLog("Warning[clientSock] {002}: Verbindung wurde hergestellt (vom clienten)", 2);
			System.out.println("verbindung wurde hergestellt (vom clienten)");
			
			try {
				brC = new BufferedInputStream(clientSock.getInputStream());
			} catch (IOException e) {
				writeLog("Error[runServer] {004}: "+ e.getMessage(), 1);
			}
			try {
				pwC = new BufferedOutputStream(clientSock.getOutputStream());
			} catch (IOException e) {
				writeLog("Error[runServer] {005}: "+ e.getMessage(), 1);
			}
			
			try {
				byte[] cach = new byte[7];
				int cachSize;
				while((cachSize = brC.read(cach))!= -1 && wait){
					line = new String(cach);
					if(checkPwd(line)){
						this.run();
						wait=false;
						
					}else{
						pwC.write("Invalide Password\r\n".getBytes());
						pwC.flush();
						wait = true;
					}
				}
			} catch (IOException e) {
				writeLog("Error[runServer] {006}: "+ e.getMessage(), 1);
			}
			
		}
		
		public void run(){
			setStreams(host);
			
			new Thread(new Runnable(){
				public void run(){
					try {
						System.out.println("wird gelesen");
						
						
						while(toServer.isConnected()  && connection){
						pwC.write("OK2\r\nicy-caps11\r\n\r\n".getBytes());
						pwC.flush();
						byte[] chunk = new byte[Integer.parseInt(users.get(userId)[2])/8];
						int chunkSize;
				
						while((chunkSize = br.read(chunk)) != -1){
							//System.out.println(line1);
							//pwC.print(line1);
							pwC.write(chunk);
							pwC.flush();
						}
						}
					} catch (IOException e) {
						writeLog("Error[runServer] {007}: "+ e.getMessage(), 1);
						kill();
					}
				}
			}).start();
			
			new Thread(new Runnable(){
				public void run(){
					try {
						pw.write((x + "\r\n").getBytes());
						pw.flush();
						

						while(toServer.isConnected() && connection){
						byte[] chunk = new byte[Integer.parseInt(users.get(userId)[2])/8];
						int chunkSize;
				
						while((chunkSize = brC.read(chunk)) != -1){
							//System.out.println(line1);
							//pw.print(line1);
							pw.write(chunk);
							pw.flush();
						}
						}
					} catch (IOException e) {
						writeLog("Error[runServer] {008}: "+ e.getMessage(), 1);
						kill();
					}
				}
			}).start();
		}
		
		private void kill(){
			wait  = true;
			connection = false;
		}
		
	}
 

darkeye2

Bekanntes Mitglied
der darf ja net schlafen, wenn er schläft, dann wird da ja nix übertragen, und er muss den gesammten ankommenden stream ja wieder weiterleiten (und zwar so schnell wie möglich)
 
G

Gast2

Gast
Aber wenns nichts zu tun gibt sollte der Thread auch nicht in ner dauerschleife laufen :)
 

darkeye2

Bekanntes Mitglied
aber normal gibts ja immer was zu tun, denn wenn nix gesendet wird, heißt es, dass die verbindung getrennt wurde, dann wird der thread ja automatisch gekillt, und dann läuft nur noch der abfrage thread, aber die auslastung wird durch den clientHandler hervorgerufen
 

Nicer

Bekanntes Mitglied
Du Solltest solange wie da nix zu tun ist die ganze sache entweder ganz unterbrechen und bei bedarf starten oder wenigstens sleepen. Sonst rechnet er ja die ganze zeit im kreis und das kostet natürlich krass auslastung.
 

darkeye2

Bekanntes Mitglied
was das programm machen muss:
die ganze zeit auf den port 7001 hören und immer wenn ein client eine anfrage starten, ob bereits ein client verbunden ist, und entweder nen clientHandler starten oder oben ablehnen, das verbraucht gradmal 0.3% CPU auslastunge, code sieht so aus:

Java:
public void runServer(Shoutcast sev){
        try{
            while(live){
                if(wait){
                    Socket client = server.accept();
                    ch = new clientHandler(client);
                }
            }
        } catch(IOException e){writeLog("Error[runServer] {003}: "+ e.getMessage(), 1);}
    }

das scheint ja perfekt zu klappen, verbindet sich nun ein client wird der clentHandler gestartet und schon hab ich 100% auslastung, obwohl der clientHandler nur so lange exestiert, wie daten gesendet werden!

Und da muss wohl ein fehler im code sein, denn ich grad net finde

Java:
    protected class clientHandler extends  Thread{
        protected Socket clientSock;
        
        clientHandler(Socket cl){
            clientSock = cl;
            connection  = true;
            writeLog("Warning[clientSock] {002}: Verbindung wurde hergestellt (vom clienten)", 2);
            System.out.println("verbindung wurde hergestellt (vom clienten)");
            
            try {
                brC = new BufferedInputStream(clientSock.getInputStream());
            } catch (IOException e) {
                writeLog("Error[runServer] {004}: "+ e.getMessage(), 1);
            }
            try {
                pwC = new BufferedOutputStream(clientSock.getOutputStream());
            } catch (IOException e) {
                writeLog("Error[runServer] {005}: "+ e.getMessage(), 1);
            }
            
            try {
                byte[] cach = new byte[7];
                int cachSize;
                while((cachSize = brC.read(cach))!= -1 && wait){
                    line = new String(cach);
                    if(checkPwd(line)){
                        this.run();
                        wait=false;
                        
                    }else{
                        pwC.write("Invalide Password\r\n".getBytes());
                        pwC.flush();
                        wait = true;
                    }
                }
            } catch (IOException e) {
                writeLog("Error[runServer] {006}: "+ e.getMessage(), 1);
            }
            
        }
        
        public void run(){
            setStreams(host);
            
            new Thread(new Runnable(){
                public void run(){
                    try {
                        System.out.println("wird gelesen");
                        
                        
                        while(toServer.isConnected()  && connection){
                        pwC.write("OK2\r\nicy-caps11\r\n\r\n".getBytes());
                        pwC.flush();
                        byte[] chunk = new byte[Integer.parseInt(users.get(userId)[2])/8];
                        int chunkSize;
                
                        while((chunkSize = br.read(chunk)) != -1){
                            //System.out.println(line1);
                            //pwC.print(line1);
                            pwC.write(chunk);
                            pwC.flush();
                        }
                        }
                    } catch (IOException e) {
                        writeLog("Error[runServer] {007}: "+ e.getMessage(), 1);
                        kill();
                    }
                }
            }).start();
            
            new Thread(new Runnable(){
                public void run(){
                    try {
                        pw.write((x + "\r\n").getBytes());
                        pw.flush();
                        
 
                        while(toServer.isConnected() && connection){
                        byte[] chunk = new byte[Integer.parseInt(users.get(userId)[2])/8];
                        int chunkSize;
                
                        while((chunkSize = brC.read(chunk)) != -1){
                            //System.out.println(line1);
                            //pw.print(line1);
                            pw.write(chunk);
                            pw.flush();
                        }
                        }
                    } catch (IOException e) {
                        writeLog("Error[runServer] {008}: "+ e.getMessage(), 1);
                        kill();
                    }
                }
            }).start();
        }
        
        private void kill(){
            wait  = true;
            connection = false;
        }
        
    }
 
M

Marcinek

Gast
Ja, weil dieser Aufruf:

Code:
  Socket client = server.accept();
bockierned ist.

Er hält den Trhead an: Deine anderen Threads haben offensichtlich nicht diese Funktion.
 

darkeye2

Bekanntes Mitglied
hmm, selbst mit thread.sleep ist die serverauslastung immer noch bei 100% aber seit einer kleinen änderung hab ich noch ein problem:

ich habe die main methode vorher so gehabt:
Java:
	public static void main(String[] args) {
			new Shoutcast("11.11.11.11");
	}
das hat auch prima funktioniert, da das prog auf dem server läuft muss ich ja immer per console starten.

nun brauche ich aber eine überhabe und hab die main so verändert:
Java:
	public static void main(String[] args) {
		if(args.length != 0){
			new Shoutcast("11.11.11.11", args[0]);
		}else{
			new Shoutcast("11.11.11.11", "test");
		}
	}

seit dem hab ich das problem dass das programm sich beendet, sobald ich die console bei mir auf dem rechner zumache (putty)
 

Michael...

Top Contributor
Was mir so beim Überfliegen aufgefallen ist:
In Zeile 27 der Klasse clientHandler (Klassennamen beginnen in Java üblicher Weise mit Grossbuchstaben
Rufst die direkt
Code:
this.run()
auf. Diese Methode des Threads wird nicht direkt sondern über die start() des Threads aufgerufen, sonst läuft das ganze nicht in einem separaten Thread.
 

darkeye2

Bekanntes Mitglied
danke, habs ausgebessert, wobei es weder die cpu auslastung gesenkt hat, noch das mit der console gelöst hat, aber immerhin ein fehler weniger^^

Hoffe es weiß einer, wieso ich die console jetzt net schließen darf ...
 

Illuvatar

Top Contributor
Also, ich hab das sehr starke Gefühl da ist noch einiges mehr im Argen, wenn ich den Code so überflieg... aber solang du kein KSKB postest, oder genauer beschreibst was das Programm machen soll, wird wahrschenlich keiner sich das mal genauer anschauen können.

Aber zu den Problemen die du beschrieben hast:
  • Die 100% CPU-Auslastung kommen von dem Code hier:
    Java:
                while(live){
                    if(wait){
                        Socket client = server.accept();
                        ch = new clientHandler(client);
                    }
                }
    Im clientHandler wird dann wait erstmal auf
    Code:
    false
    gesetzt. Hast du schonmal überlegt, was der Code da macht wenn
    Code:
    wait==false
    ist? Er überprüft, so oft wie dein Prozessor es hinkriegt, ob wait nicht vielleicht doch wieder
    Code:
    true
    ist.
  • Das mit der Konsole kann nicht an der main-Methode da liegen, aber du hast ja offensichtlich noch mehr als diese Methode geändert (mindestens mal den Konstruktor)... aber bist du ganz sicher, dass du das Programm auf die gleiche Art und Weise startest wie früher? Meine Kristallkugel vermutet das Problem eher in der Ecke.
 

KSG9|sebastian

Top Contributor
server.accept() blockt bis eine Verbindung ankommt -> daran hängt's nicht mit der Auslastung.

Allerdings ist der Code dermaßen verwirrend das man nicht durchsteigt.

Zuerstmal:

- Implementier Runnable, innerhalb der run()-Methode dann den Code zum lesen vom Socket.
- Sobald eine Verbindung ankommt (Socket.accept()), erzeug dieses "Runnable" und starte es (mittels run() !!)

Es gibt hier in der FAQ auch Beispiele zum Thema Threading, Client/Server..
 
J

JohannisderKaeufer

Gast
Mein Vorschlag wäre das:

Java:
            while(live){
                Socket client = server.accept();
                if(wait){
                    ch = new clientHandler(client);
                }
            }

Requests annehmen server.accept() blockt ja.
Dann entscheiden, ob dieser client bedient wird.
 

darkeye2

Bekanntes Mitglied
schon mal danke für die tipps, hier nochmal die genau beschreibung, was das prog macht:
ein cleint (nicht von mir programmiert) verbindet sich zum programm. Danach sendet der client eine passwort, dieses wird mit einer liste aller nutzer verglichen, ist es eingetragen und richtig, so verbindet sich mein programm mit einem anderen prog auf einen anderen server. Ab jetzt wird der datentransfer vom clienten direkt an das andere serverpgrogramm weitergeleitet, bis einer von beiden die verbindung trennt. Das progg soll tag und nacht laufen können, allerdings laufen die transfer threads nur, wenn ein client daten sendet (also immer wenn er verbunden ist).

Meine umsetzung sieht (nach euren tipps) jetzt so aus (ports, ips, passwörter und pfade wurden hier verändert):
Java:
Shoutcast(String ip, String pw){
		
		try{
			//Server zum verbinden
			x = pw;
			System.out.println("Programm (by darkeye) wurde Fehlerfrei gestartet");
			writeLog("Warning[Constructor] {001}: Programm (by darkeye) wurde Fehlerfrei gestartet", 2);
			host = ip;
			server = new ServerSocket(1001);
			readUsers();
			runServer(this);
		} catch(IOException e){writeLog("Error[Constructor] {002}: "+ e.getMessage(), 1);}
		
	}
	
	public void runServer(Shoutcast sev){
		try{
			while(live){
				Socket client = server.accept();
				if(wait){
					ch = new clientHandler(client);
				}
			}
		} catch(IOException e){writeLog("Error[runServer] {003}: "+ e.getMessage(), 1);}
	}
	
	protected class clientHandler extends  Thread{
		protected Socket clientSock;
		
		clientHandler(Socket cl){
			clientSock = cl;
			connection  = true;
			wait = true;
			writeLog("Warning[clientSock] {002}: Verbindung wurde hergestellt (vom clienten)", 2);
			System.out.println("verbindung wurde hergestellt (vom clienten)");
			
			try {
				brC = new BufferedInputStream(clientSock.getInputStream());
			} catch (IOException e) {
				writeLog("Error[clientSock] {004}: "+ e.getMessage(), 1);
			}
			try {
				pwC = new BufferedOutputStream(clientSock.getOutputStream());
			} catch (IOException e) {
				writeLog("Error[clientSock] {005}: "+ e.getMessage(), 1);
			}
			
			try {
				byte[] cach = new byte[7];
				int cachSize;
				while((cachSize = brC.read(cach))!= -1 && wait){
					line = new String(cach);
					if(checkPwd(line)){
						this.start();
						wait=false;
						
					}else{
						pwC.write("Invalide Password\r\n".getBytes());
						pwC.flush();
						wait = true;
					}
				}
			} catch (IOException e) {
				writeLog("Error[clientWhile] {006}: "+ e.getMessage(), 1);
			}
			
		}
		
		public void run(){
			setStreams(host);
			
			new Thread(new Runnable(){
				public void run(){
					try {
						writeLog("Connection[Stream] {001}: " +users.get(userId)[0]+ " ist nun auf Sendung ["+users.get(userId)[2]+"]", 3);
						writeLog("Warning[Reader1] {002}: Clientdaten werden nun weitergeleitet", 2);
						
						
						if(toServer.isConnected()  && connection){
						byte[] chunk = new byte[5];
						int chunkSize;
				
						while((chunkSize = br.read(chunk)) != -1){
							//System.out.println(line1);
							//pwC.print(line1);
							pwC.write(chunk);
							pwC.flush();
							Thread.sleep(600);
						}
						}
					} catch (IOException e) {
						writeLog("Error[Reader1] {007}: "+ e.getMessage(), 1);
						writeLog("Warning[Reader1] {003}: Verbindung wurde vom Server geschlossen", 2);
						kill();
					} catch (InterruptedException e) {
						writeLog("Error[Reader1] {015}: "+ e.getMessage(), 1);
						writeLog("Warning[Reader1] {004}: Verbindung wurde vom Server geschlossen", 2);
						kill();
					}
					writeLog("Warning[Reader1] {005}: Verbindung zwischen Server und "+users.get(userId)[0]+" wurde geschlossen!", 2);
					kill();
				}
			}).start();
			
			new Thread(new Runnable(){
				public void run(){
					try {
						pw.write((x + "\r\n").getBytes());
						pw.flush();
						

						while(toServer.isConnected() && connection){
						byte[] chunk = new byte[(Integer.valueOf(users.get(userId)[2]))/8*1000];
						int chunkSize;
				
						while((chunkSize = brC.read(chunk)) != -1){
							//System.out.println(new String(chunk));
							//pw.print(line1);
							pw.write(chunk);
							pw.flush();
							Thread.sleep(1000);
						}
						}
					} catch (IOException e) {
						writeLog("Error[Reader2] {008}: "+ e.getMessage(), 1);
						writeLog("Warning[Reader2] {007}: Verbindung wurde vom Server geschlossen", 2);
						kill();
					} catch (InterruptedException e) {
						writeLog("Error[Reader2] {016}: "+ e.getMessage(), 1);
						writeLog("Warning[Reader2] {008}: Verbindung wurde vom Server geschlossen", 2);
						kill();
					}
					writeLog("Warning[Reader2] {006}: Verbindung zwischen Server und "+users.get(userId)[0]+" wurde geschlossen!", 2);
					kill();
				}
			}).start();
		}
		
		private void kill(){
			writeLog("Connection[Stream] {002}: " +users.get(userId)[0]+ " ist jetzt nicht mehr auf Sendung ["+users.get(userId)[2]+"]", 3);
			wait  = true;
			connection = false;
		}
		
	}
	
	private void readUsers(){
		String path = System.getProperty("user.dir")+"/users.sbd";
		BufferedReader in;
		try {
			in = new BufferedReader(new FileReader(path));
			String zeile = null;
			while ((zeile = in.readLine()) != null) {
				users.add(zeile.split(" "));
			}
		} catch (FileNotFoundException e) {
			writeLog("Error[readUsers] {009}: "+ e.getMessage(), 1);
		} catch (IOException e) {
			writeLog("Error[readUsers] {010}: "+ e.getMessage(), 1);
		}
	}
	
	private boolean checkPwd(String pw){
		for(int i =0; i< users.size(); i++){
			if(users.get(i)[1].equals(pw)){
				userId = i;
				return true;
			}
		}
		
		return false;
	}
	
	private void setStreams(String ip){
		host = new String(ip);
		try {
			toServer = new Socket(host, 1000);
		} catch (UnknownHostException e) {
			writeLog("Error[setStreams] {011}: "+ e.getMessage(), 1);
		} catch (IOException e) {
			writeLog("Error[setStreams] {012}: "+ e.getMessage(), 1);
		}
		
		//reader und  writer
		InputStream input = null;
		try {
			input = toServer.getInputStream();
		} catch (IOException e1) {
			writeLog("Error[setStreams] {013}: "+ e1.getMessage(), 1);
		}
		br = new BufferedInputStream(input);
		try {
			pw = new BufferedOutputStream(toServer.getOutputStream());
		} catch (IOException e1) {
			writeLog("Error[setStreams] {014}: "+ e1.getMessage(), 1);
		}
	}
	
	private void writeLog(String logStr, Integer mode){
		String path = null;
		if(mode == 1){
			path =  System.getProperty("user.dir")+"/www/virtual/domain.de/htdocs/VZ/SBD_ERROR.log";
		}else if(mode == 2){
			path =  System.getProperty("user.dir")+"/www/virtual/domain.de/htdocs/VZ/SBD_Event.log";
		}else{
			path =  System.getProperty("user.dir")+"/www/virtual/domain.de/htdocs/VZ/SBD_Connection.log";
		}
		try {
			RandomAccessFile raf = new RandomAccessFile(path, "rw");
			raf.seek(raf.getChannel().size());
			raf.writeBytes("["+sdf.format(new Date())+"] "+logStr+"\r\n");
			raf.close();
		} catch (IOException e) {
			writeLog("Error[writeLog] {001}: "+ e.getMessage(), 1);
			writeLog(logStr, mode);
		}
	}
	
	
	
	
	public static void main(String[] args) {
		if(args.length != 0){
			new Shoutcast("11.11.11.11", args[0]);
		}else{
			new Shoutcast("11.11.11.11", "defaultWert");
		}
	}

zum starten des progs:
ich habe es früher mit:
java -jar Programmname.jar
gestartet und jetzt ist es halt
java -jar Programmname.jar übergabeString
 
Zuletzt bearbeitet:

Michael...

Top Contributor
Kannst Du es mit javaw nicht gleich ohne Konsole starten?
Code:
javaw -jar Programmname.jar übergabeString
 

darkeye2

Bekanntes Mitglied
da es ein linux server ist, ist javaw nicht vorhanden, aber auch das starten als hintergrundprozess ändert nix daran, dass das prog weg ist, sobald putty geschlossen wird
 

Michael...

Top Contributor
Hab nicht viel Erfahrung mit putty.
Aber eventuell kann man ein Shellscript auf dem Server ablegen, das einfach nur den java Aufruf enthält und dieses Script ruft man dann via putty auf.
 

darkeye2

Bekanntes Mitglied
habs ausprobiert, und hat nichts gebracht, sobald putty geschlossen wird ist das prog auch weg .... ist eigenartig, aber ich finde den fehler net, hoffe jemand hat noch ne idee
 

darkeye2

Bekanntes Mitglied
Danke, schein zu funktionieren, zwar sind noch paar fehler drin, aber nix all zu wichtiges, die auslastung ist jetzt nicht mehr bei 100 sondern bei 1-2% und es geht nicht plötzlich aus, wenn man die console schließt, jetzt hoffe ich, dass es längere zeit fehlerfrei laufen kann (zumindest ohne grobe fehler).

werde mich dann wieder melden.
Danke an alle, die hier mitgeholfen und tipps gegeben haben.
 

Ähnliche Java Themen

Neue Themen


Oben