Performance verbessern

Dark Ranger

Erfahrenes Mitglied
chatserver.java
Code:
import java.net.*;
import java.io.*;
import java.util.*;

public class chatserver implements Runnable
{
	public static final int PORT = 8765;
	protected ServerSocket listen;
	protected Vector connections;
	Thread connect;
	
	public static void main(String[] args)
	{
		new chatserver();
	}
	
	public chatserver()
	{
		try
		{
			listen = new ServerSocket(PORT);
		} catch (IOException e)
		{
			System.err.println("Fehler beim Erzeugen der Sockets:"+e);
			System.exit(1);
		}
	
		connections = new Vector();
	
		connect = new Thread(this);
		connect.start();
	}
	
	public void run()
	{
		try
		{
			while(true)
			{
				Socket client=listen.accept();
	
				connection c = new connection(this, client);
				connections.addElement(c);
			}
		} catch (IOException e)
		{
			System.err.println("Fehler beim Warten auf Verbindungen:"+e);
			System.exit(1);
		}
	}

	public void broadcast(String msg)
	{
		int i;
		connection you;
	
		for (i=0; i<connections.size(); i++)
		{
			you = (connection) connections.elementAt(i);
			you.out.println(msg);
		}
	}
}

class connection extends Thread
{
	protected Socket client;
	protected DataInputStream in;
	protected PrintStream out;
	protected chatserver server;

	public connection(chatserver server, Socket client)
	{
		this.server=server;
		this.client=client;
	
		try
		{
			in = new DataInputStream(client.getInputStream());
			out = new PrintStream(client.getOutputStream());
		} catch (IOException e)
		{
			try { client.close(); } catch (IOException e2) {} ;
			System.err.println("Fehler beim Erzeugen der Streams: " + e);
			return;
		}
	
		this.start();
	}

	public void run()
	{
		String line;
	
		try
		{
			while(true)
			{
				line=in.readLine();
				if(line!=null)
					server.broadcast(line);
			}
		} catch (IOException e)
		{
			System.out.println("Fehler:" + e);
		}
	}
}

chatapplet.java
Code:
import java.net.*;
import java.io.*;
import java.awt.*;
import java.applet.*;

public class chatapplet extends Applet implements Runnable
{
	public static final int PORT = 8765;
	Socket socket;
	DataInputStream in;
	PrintStream out;
	TextField inputfield;
	TextArea outputarea;
	Thread thread;
	
	public void init()
	{
		inputfield = new TextField();
		outputarea = new TextArea();
		outputarea.setFont( new Font("Dialog", Font.PLAIN, 12));
		outputarea.setEditable(false);
	
		this.setLayout(new BorderLayout());
		this.add("South", inputfield);
		this.add("Center", outputarea);
			this.setBackground(Color.lightGray);
		this.setForeground(Color.black);
		inputfield.setBackground(Color.white);
		outputarea.setBackground(Color.white);
	}
	
	public void start()
	{
		try
		{
			socket = new Socket(this.getCodeBase().getHost(), PORT);
			in = new DataInputStream(socket.getInputStream());
			out = new PrintStream(socket.getOutputStream());
		} catch (IOException e)
		{
			this.showStatus(e.toString());
			say("Verbindung zum Server fehlgeschlagen!");
			System.exit(1);
		}
	
		say("Verbindung zum Server aufgenommen...");
	
		if (thread == null)
		{
			thread = new Thread(this);
		thread.setPriority(Thread.MIN_PRIORITY);
			thread.start();
		}
	}

	public void stop()
	{
		try
		{
			socket.close();
		} catch (IOException e)
		{
			this.showStatus(e.toString());
		}
	
		if ((thread !=null) && thread.isAlive())
		{
			thread.stop();
			thread = null;
		}
	}
	
	public void run()
	{
		String line;
	
		try
		{
			while(true)
			{
				line = in.readLine();
				if(line!=null)
		outputarea.appendText(line+'\n' );
			}
		} catch (IOException e) { say("Verbindung zum Server abgebrochen"); }
	}

	public boolean action(Event e, Object what)
	{
		if (e.target==inputfield)
		{
			String inp=(String) e.arg;
		out.println(inp);
			inputfield.setText("");
			return true;
		}
		return false;
	}
	
	public void say(String msg)
	{
		outputarea.appendText("*** "+msg+" ***\n");
	}


}

Also das ist mein Code, den ich nach einem kleinen Tutorial geschrieben habe, allerdings ist es so, dass die CPU Auslastung auf 100% steigt, wenn ich die chatserver.java ausführe.

Gibt es vielleicht eine möglichkeit das ganze zu verbessern?
 
Zuletzt bearbeitet:
Hallo,

ich habe zwar noch nicht soviel mit Netzwerk-Programmierung gemacht, aber ich glaube nicht so ganz, dass es daran liegt, dass nicht die java.nio verwendet wird.

Ich glaube eher dass es an der while-Schleife liegt die endlos läuft und bei jedem durchlauf aus dem socket liest.

Code:
while(true)
{
	line=in.readLine();
	if(line!=null)
		server.broadcast(line);
}

Ich habe auch im moment keinen Lösungsvorschlag :-(
Wie gesagt, in der Richtung noch nicht so viel gemacht, aber vielleicht hilft meine Anmerkung ja zum Finden einer Lösung.
Lasse mich auch gerne aufklären :-)

MFG

zEriX
 
Irgendwie komme ich damit nicht klar es in meinen Code einzubauen!
Habe wirklich keinen Plan wie und wo ich das alles abändern muss damit es mit dem nio funktioniert

Ich hasse Englische Sachen, auch wenn ich als Anwendungsentwickler des öfteren drauf angewiesen bin -.- Naja muss man durch, aber die Links von oben verstehe ich nicht, da habe ich echt mal keinen Plan

Edit: Habe ich auch schon gedacht das es an der Endlosschleife liegt, weil er ja ständig schaut ob es irgendetwas neues gibt! Kann man da nicht einen kleinen break einbauen? Oder ist dann die Gefahr groß das er irgendwas nicht mitbekommt der Server?
 
Zuletzt bearbeitet:
Ja, Zerix hat ganz recht :) (wann hat er auch mal unrecht?) Also klar, diese Endlosschleife ist der Grund, warum soviel Rechenzeit "verschwendet" wird. Und die Rechenzeit wird verschwendet, weil du schon einen Non-Blocking-Socket hast (zumindest verwendest du ihn im Moment so :) )

Also diese Non-Blocking-Sockets sind leider das Problem und nicht die Lösung :) Weil das Programm an der Stelle halt nicht wartet, sondern immer und immer wieder null ausliest - je mehr Rechenzeit vorhanden ist umso schneller, deswegen ist das ganze so rechenintensiv.

Ich bin gerade mit was ganz anderem dran ... bei mir werden DatagrammSockets verwendet, die sind recht praktisch, weil die Methode receive blockierend ist, d.h. solange keine Daten vorhanden sind, wartet das Programm an der Stelle. Aber ich glaub sowas lässt sich für einen Chat leider nicht benutzen.

Am besten gehst du von diesem Readln weg, denn das liefert leider immer null zurück, wenn gerade nichts zu lesen ist. Schau mal ob du eine andere Methode (vielleicht auch in einer anderen Art von Stream) findest, die blockierend ist. Dann ist dein Rechenzeitproblem gelöst.

Eine andere Möglichkeit wäre einfach ein Thread.sleep einzubauen. Ich glaub es kann nicht schaden, den Socket nur 2 mal pro Sekunde oder so auszulesen, so schnell kann ja eh keiner tippen :)

Oder ... naja, oder du musst von diesem "Polling" weg, also dem immer wieder nach neuen Nachrichten anfragen. Eine Möglichkeit wäre ein zweiter Socket pro Client. Also der Client baut die Verbindung auf und der entsprechende Socket bleibt dann offen und wird gespeichert um Nachrichten zum Client zu schicken. Jede weitere Nachricht schickt der Client dann über einen zweiten Socket (also immer wieder über einen anderen, neuen), der immer wieder sofort geschlossen wird. Sehr unschön, zugegeben, aber es müsste funktionieren. Und da die accept-Methode vom ServerSocket ja blockierend ist auch erheblich weniger Rechenzeit verbrauchen.
 
Zuletzt bearbeitet:
Habe nun ein Thread.sleep(100) eingebaut, damit geht es erstmal und wir sind mit drei man am chatten und bis jetzt waren noch alle Daten da die da sein sollten! ^^

Edit: Mhhh kann ich ne PHP-Variable irgendwie an das Java Applet übergeben?
 
Zuletzt bearbeitet:
Habs nicht so genau gelesen .... :-(

Hier ein Chatserver für Telnet ohne Bremse.... CPU Last beim warten 0 %

Java:
package de.tutorials;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

/**
 * 
 * Chatserver für Telnetclients
 * starte Telnet mit localhost oder ip und Port 9000
 * 
 * @author Jo
 *
 */
public class ChatServer extends Thread {

	private static List<ChatServer> clients = new ArrayList<ChatServer>();
	private Socket socket;
	private BufferedReader reader ;
	private PrintWriter out;
	
	ChatServer(Socket socket) throws IOException{
		this.socket = socket;
		reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		out = new PrintWriter(socket.getOutputStream());
		clients.add(this);
	}
	
	
	@Override
	public void run() {
		String nickname = null;
		String eingabe = null;
		try {
			
			send ("Chatserver 1.0");
			send ("Wie ist Dein Nickname?");
			nickname = reader.readLine();
			broadcast(nickname + " erscheint aus dem Nichts....");
			while ((eingabe = reader.readLine()) != null) {
				if (eingabe.equalsIgnoreCase("bye")) break;
				broadcast(nickname + ": " + eingabe);
			}
		} catch (Exception e) {
			
		}
		clients.remove(this);
		broadcast(nickname + " verschwindet in einer Rauchwolke!");
		if (socket.isConnected())
			try {
				socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		
	}
	
	private void send(String message) {
		out.println(message);
		out.flush();
	}


	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		
		ServerSocket serverSocket = new ServerSocket(9000);
		System.out.println("Socket an Port 9000 etabliert!");
		
		while (true) {
			System.out.print("Warte auf eingehenden Verbindungen...");
			Socket socket = serverSocket.accept();
			System.out.println("ok!");
			System.out.println(socket + " erkannt");
			System.out.println("Starte Handler");
			new ChatServer(socket).start();
		}

	}
	
	public static synchronized void broadcast(String message) {
		for(ChatServer client: clients)
			client.send(message);
	}

}
 
Zuletzt bearbeitet:
Da ich bis auf den BufferedReader und den DataInputStream keinen großen Unterschied gesehen habe, habe ich Deinen Server mal laufen lassen. Er verbraucht keine 100%. Selbst wenn ich mit einem Telnetclient draufgehe, hält er sich mit CPU Verbrauch vornehm zurück. Er dümpelt im einstelligen Bereich. Dein Problem liegt beim Client, oder sonstwo.

Gruß
 
Habe Dein Applet auf Frame umgeschrieben.

Hängt sich tadellos auf Deinen Server. CPU-Usage von beiden zusammen 1 %.

Java:
package de.tutorials;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Event;
import java.awt.Font;
import java.awt.Frame;
import java.awt.TextArea;
import java.awt.TextField;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;

public class chatapplet extends Frame implements Runnable
{
	public static final int PORT = 8765;
	Socket socket;
	DataInputStream in;
	PrintStream out;
	TextField inputfield;
	TextArea outputarea;
	Thread thread;
	
	chatapplet() {
		setSize(500, 500);
		init();
		start();
		setVisible(true);
		
	}
	
	public void init()
	{
		inputfield = new TextField();
		outputarea = new TextArea();
		outputarea.setFont( new Font("Dialog", Font.PLAIN, 12));
		outputarea.setEditable(false);
	
		this.setLayout(new BorderLayout());
		this.add("South", inputfield);
		this.add("Center", outputarea);
			this.setBackground(Color.lightGray);
		this.setForeground(Color.black);
		inputfield.setBackground(Color.white);
		outputarea.setBackground(Color.white);
	}
	
	public void start()
	{
		try
		{
			socket = new Socket("localhost", PORT);
			in = new DataInputStream(socket.getInputStream());
			out = new PrintStream(socket.getOutputStream());
		} catch (IOException e)
		{
			
			System.exit(1);
		}
	
		say("Verbindung zum Server aufgenommen...");
	
		if (thread == null)
		{
			thread = new Thread(this);
		thread.setPriority(Thread.MIN_PRIORITY);
			thread.start();
		}
	}

	public void stop()
	{
		try
		{
			socket.close();
		} catch (IOException e)
		{
			System.out.println(e.getMessage());
		}
	
		if ((thread !=null) && thread.isAlive())
		{
			thread.stop();
			thread = null;
		}
	}
	
	public void run()
	{
		String line;
	
		try
		{
			while(true)
			{
				line = in.readLine();
				if(line!=null)
		outputarea.appendText(line+'\n' );
			}
		} catch (IOException e) { say("Verbindung zum Server abgebrochen"); }
	}

	public boolean action(Event e, Object what)
	{
		if (e.target==inputfield)
		{
			String inp=(String) e.arg;
		out.println(inp);
			inputfield.setText("");
			return true;
		}
		return false;
	}
	
	public void say(String msg)
	{
		outputarea.appendText("*** "+msg+" ***\n");
	}
	public static void main(String[] args) {
		new chatapplet();
	}

}

Welche Umgebung verwendest Du? Ich habe Java 6 unter XP.
 
c:\java -version
java version "1.5.0_03"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_03-b07)
Java HotSpot(TM) Client VM (build 1.5.0_03-b07, mixed mode, sharing)


Meinst du das? Also habe da irgendso ein jdk mir geholt

Wenn ich dein Applet benutze:
Code:
Laden: chatapplet.class ist nicht öffentlich oder hat keinen öffentlichen Autor.
java.lang.IllegalAccessException: Class sun.applet.AppletPanel can not access a member of class chatapplet with modifiers ""
	at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
	at java.lang.Class.newInstance0(Unknown Source)
	at java.lang.Class.newInstance(Unknown Source)
	at sun.applet.AppletPanel.createApplet(Unknown Source)
	at sun.plugin.AppletViewer.createApplet(Unknown Source)
	at sun.applet.AppletPanel.runLoader(Unknown Source)
	at sun.applet.AppletPanel.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
 
Zuletzt bearbeitet:
Zurück