# 100% auslastung?



## darkeye2 (2. Okt 2010)

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

```
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;
		}
		
	}
```


----------



## Gast2 (2. Okt 2010)

In deinen Schleifen fehlt nen Thread.sleep();


----------



## darkeye2 (2. Okt 2010)

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)


----------



## Gast2 (2. Okt 2010)

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


----------



## darkeye2 (2. Okt 2010)

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 (2. Okt 2010)

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 (3. Okt 2010)

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:


```
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


```
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;
        }
        
    }
```


----------



## Marcinek (3. Okt 2010)

Ja, weil dieser Aufruf:


```
Socket client = server.accept();
```
bockierned ist.

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


----------



## darkeye2 (3. Okt 2010)

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:

```
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:

```
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... (3. Okt 2010)

Was mir so beim Überfliegen aufgefallen ist:
In Zeile 27 der Klasse clientHandler (Klassennamen beginnen in Java üblicher Weise mit Grossbuchstaben
Rufst die direkt 
	
	
	
	





```
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 (3. Okt 2010)

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 (3. Okt 2010)

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:

```
while(live){
                if(wait){
                    Socket client = server.accept();
                    ch = new clientHandler(client);
                }
            }
```
Im clientHandler wird dann wait erstmal auf 
	
	
	
	





```
false
```
 gesetzt. Hast du schonmal überlegt, was der Code da macht wenn 
	
	
	
	





```
wait==false
```
 ist? Er überprüft, so oft wie dein Prozessor es hinkriegt, ob wait nicht vielleicht doch wieder 
	
	
	
	





```
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 (4. Okt 2010)

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..


----------



## JohannisderKaeufer (4. Okt 2010)

Mein Vorschlag wäre das:


```
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 (4. Okt 2010)

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):

```
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


----------



## darkeye2 (6. Okt 2010)

hat keiner eine idee, wie ich  das problem mit dem starten in der console lösen kann?

verzweifle da immer noch dran


----------



## Michael... (6. Okt 2010)

Kannst Du es mit javaw nicht gleich ohne Konsole starten?

```
javaw -jar Programmname.jar übergabeString
```


----------



## darkeye2 (6. Okt 2010)

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... (6. Okt 2010)

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 (6. Okt 2010)

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


----------



## planetenkiller (6. Okt 2010)

darkeye2 hat gesagt.:


> 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


Das ist normal bei ssh. Nach dem logout werden alle deine Prozesse gekillt. Stichwort nohub(nohup - Wikipedia, the free encyclopedia) oder später sogar ein init-script.


----------



## darkeye2 (6. Okt 2010)

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.


----------

