Neuer Thread für jeden Benutzer im Chat?

javaprogger1987

Erfahrenes Mitglied
Und zwar hab ich mal eine allgemeine Frage:
Ich bin dabei einen Chat (ja schon wieder ;)) mit Sockets zu programmieren, aber ich bin mir nicht sicher, wie ich die Serverseite realisieren muss..
Ein Thread für jeden Benutzer muss ja dann sein oder?
Wie ist das mit dem Speicherverbrauch dann (z.b. bei 1000 Usern?). Ist das noch im Rahmen oder wird das zuviel?
 
Wird eigentlich irgendwo die Technik erklärt, wie man einen ThreadPool anlegt? Ich habe schon oft davon gehört, eben auch in Verbindung mit Webservern... aber so wirklich hab ich nix dazu gefunden.
 
Hallo!

Unter Java 5 gibts im concurrent Package einige neue Klassen. Darunter auch ThreadPoolExecutor... <- anschauen.

Ansonsten schau dir mal Doug Lea's Conncurrent Bibliothek an... (sie bildet IMHO die Basis für das Java 5 Concurrent Package)
http://gee.cs.oswego.edu/dl/

Gruß Tom
 
Danke für die Antworten erst mal!
Die Threads sollen relativ wenig machen, nur die Sockets zu den Clients verwalten und auf neue Nachrichten der Clients warten... (ggf. auch noch senden.. aber das würde ja nicht den UNterschied machen)


Mit dem Threadpool ist nur sinnvoll für kurzlebige Threads die dann wieder verwendet werden Hab ich das richtig verstanden? Bitte um Aufklärung :)
 
Klingt schon nicht schlecht.. Ich hatte auch noch eine Idee, nämlich folgendes:
1. Client verbindet zum Server
2. Socket wird in Liste abgelegt
3. Wenn der Client eine Anfrage senden will sendet er seine Id (index in der liste) über z.b. http an den sever und der startet dann einen Thread (nicht unbedingt einen Thread weil der http-Request auch schon in einem seperaten Thread gestartet wird aber das sind details ;)) der dann die Nachricht abfragt...

Nun habe ich folgende Fragen:
Welche Alternative hab ich zu http? (Ein InputStream vom Server wo alle Clients reinschreiben können wär gut :))
 
So Neuigkeiten :)
Hab das nun gemacht was ich im letzten Post gesagt hatte nur mit UDP... Trotzdem noch einige Fragen:
- Wie wahrscheinlich kommen UDP Pakete an? 50/50? Kann man das abschätzen?

Und noch ein Problem mit meinem Server/ Client.. Das nur angucken wenn ihr Lust/Zeit habt.. Danke:

Beim senden einer Nachricht klappt alles, aber ab der 2. Nachricht, kommen in der Klasse UDPListener immer zwei UDP-Pakete an -> "Packet!" wird zweimal ausgegeben.. Woran liegt das?

Server.java
Code:
package sockettest;
import java.net.*;
import javax.net.*;
import java.util.*;
import java.io.*;
/**
 * <p>Überschrift: </p>
 *
 * <p>Beschreibung: </p>
 *
 * <p>Copyright: Copyright (c) 2005</p>
 *
 * <p>Organisation: None</p>
 *
 * @author Tobias Viehweger
 * @version 1.0
 */
public class Server {
  public static final String UDP_PACKET_RECIEVED = "UPDRECV";
  private ServerSocket tcpConnection = null;
  private DatagramSocket udpConnection = null;
  private Vector clients = new Vector();
  private UDPListener udpThread;
  private TCPListener tcpThread;
  public Server ()
  {
	try
	{
	  //Zuerst die UDP-Verbindung erstellen
	  udpConnection = new DatagramSocket( 11834 );
	  //Dann die TCP Socket Verbindung erstellen
	  tcpConnection = new ServerSocket( 11833 );
	  //Thread, der auf Nachrichten auf dem UDP-Port wartet
	  udpThread = new UDPListener( udpConnection );
	  udpThread.start();
	  //Thread, der auf neue Clients wartet
	  tcpThread = new TCPListener( tcpConnection, clients );
	  tcpThread.start();
	  while (true)
	  {
		if (udpThread.hasNewMessages())
		{
		  byte [] arData = udpThread.getNextMessage();
		  String sIndex = new String( arData, 0, arData.length );
		  
		  int index = -1;
		  try
		  {
			index = Integer.parseInt( sIndex );
		  }
		  catch ( NumberFormatException ex1 )
		  {}
		  if (index > -1 && index < clients.size())
		  {
			//Bescheid sagen, dass das UDP Packet ankam (Sonst muss der Client es erneut senden)
			Socket sock = (Socket)clients.elementAt( index );
			sock.getOutputStream().write( UDP_PACKET_RECIEVED.getBytes() );
			//Dann Nachricht abfragen
			new MessageReciever(sock).start();
		  }
		}
		else
		{
		  try
		  {
			Thread.sleep( 100 );
		  }
		  catch ( InterruptedException ex )
		  {
		  }
		}
	  }
	}
	catch ( Exception ex )
	{
	  ex.printStackTrace();
	}
  }
  public static void main ( String[] args )
  {
	new Server();
  }
}
class MessageReciever extends Thread
{
  private Socket socket;
  public MessageReciever(Socket sock)
  {
	socket = sock;
  }
  public void run()
  {
	try
	{
	  BufferedInputStream in = new BufferedInputStream( socket.getInputStream() );
	  OutputStream out = socket.getOutputStream();
	  byte[] buf = new byte[1024 ];
	  int len;
	  while ( ( len = in.read( buf ) ) != -1 )
	  {
		System.out.write( buf, 0, len);
		out.write( buf, 0, len );
	  }
	}
	catch ( IOException ex )
	{
	}
  }
}
class TCPListener extends Thread
{
  private boolean listen;
  private Vector clients;
  private ServerSocket tcp;
  public TCPListener ( ServerSocket sock, Vector cl )
  {
	clients = cl;
	tcp = sock;
	listen = true;
  }
  public void setListening ( boolean b )
  {
	listen = b;
  }
  public void run()
  {
	while (listen)
	{
	  try
	  {
		//Auf neue TCP Verbindungen warten
		Socket next = tcp.accept();
		//Test
		System.out.println( "Neuer Socket-Client: " + next.getInetAddress() );
		//Den Client in die Liste ablegen
		clients.addElement( next );
		//Dem Client seinen Platz in der Liste mitteilen
		byte[] arData = Integer.toString( clients.indexOf( next ) ).getBytes();
		next.getOutputStream().write( arData, 0, arData.length );
	  }
	  catch ( IOException ex )
	  {
	  }
	}
  }
}
class UDPListener extends Thread
{
  private boolean listen;
  private DatagramSocket udp;
  private DatagramPacket packet;
  private List messages;
  public UDPListener (DatagramSocket con)
  {
	udp = con;
	messages =  Collections.synchronizedList(new LinkedList());
	listen = true;
  }
  public void setListening(boolean b)
  {
	listen = b;
  }
  public boolean hasNewMessages()
  {
	return !messages.isEmpty();
  }
  public byte[] getNextMessage()
  {
	if (!hasNewMessages())
	  return null;
	synchronized(messages)
	{
	  return (byte[])messages.remove(0);
	}
  }
  public void run()
  {
	while (listen)
	{
	  try
	  {
		//Paket erzeugen
		packet = new DatagramPacket( new byte[256 ], 256 ); //256 Bytes sollten locker reichen
		//Auf Nachricht warten
		udp.receive( packet );
		
		System.out.println( "Paket!" );
		//Nur uebertragene Bytes speichern
		byte [] tmpBuf = new byte[ packet.getLength() ];
		System.arraycopy( packet.getData(), 0, tmpBuf, 0, tmpBuf.length );
		//Zur Liste hinzufuegen
		messages.add( tmpBuf );
	  }
	  catch ( IOException ex )
	  {
	  }
	}
  }
}

und Client.java
Code:
package sockettest;
import java.io.*;
import java.net.*;
/**
 * <p>Überschrift: </p>
 *
 * <p>Beschreibung: </p>
 *
 * <p>Copyright: Copyright (c) 2005</p>
 *
 * <p>Organisation: None</p>
 *
 * @author Tobias Viehweger
 * @version 1.0
 */
public class Client {
  public final static byte CMD_TERMINATE_CONNECTION = -1;
  public static final String UDP_PACKET_RECIEVED = "UPDRECV";
  public Client ()
  {
	try
	{
	  System.out.print( "IP:" );
	  BufferedReader inl = new BufferedReader(new InputStreamReader(System.in));
	  String ip = inl.readLine();
	  Socket sock = new Socket( ip, 11833 );
	  //new Listener(sock).start();
	  BufferedInputStream in = new BufferedInputStream(System.in);
	  OutputStream out = sock.getOutputStream();
	  InetAddress ia = sock.getInetAddress();
	  int port = 11834;
	  DatagramPacket packet;
	  
	  //Nun erst die ID lesen
	  String id = readFromStream(sock.getInputStream());
	  System.out.println( id );
	  byte [] buf = new byte[1024];
	  int len;
	  while ( (len = in.read(buf)) != -1 )
	  {
		String str = new String( buf, 0, len);
		//UDP-Paket senden, um dem Server mitzuteilen, dass wir eine Nachricht senden wollen
		boolean sent = false;
		packet = new DatagramPacket( id.getBytes(), id.getBytes().length, ia, port );
		DatagramSocket toSocket = new DatagramSocket();
		sock.setSoTimeout(500);
		while (!sent)
		{
		  toSocket.send( packet );
		  
		  try 
		  {
			String resp = readFromStream( sock.getInputStream() );
			if (resp.equals(UDP_PACKET_RECIEVED))
			  sent = true;
		  }
		  catch (Exception e)
		  {}
		  
		}
 
		sock.setSoTimeout(0);
		
		//Nun die eigentliche Nachricht senden		
		out.write( buf, 0, len);
	  }
	}
	catch ( UnknownHostException ex )
	{
	  ex.printStackTrace();
	}
	catch ( IOException ex )
	{
	  ex.printStackTrace();
	}
  }
  /**
   * readFromStream
   *
   * @param inputStream InputStream
   * @return String
   */
  private String readFromStream ( InputStream inputStream )
  {
	String ret = null;
	BufferedInputStream in = null;
	in = new BufferedInputStream( inputStream );
	byte[] buf = new byte[ 256 ];
	int len;
	try
	{
	  if ( ( len = in.read( buf ) ) != -1 )
	  {
		ret = new String( buf, 0, len );
	  }
	}
	catch ( Exception ex )
	{
	}
	return ret;
  }
  public static void main ( String[] args )
  {
	Client client = new Client();
  }
}
 
Zurück