Warnung: file_put_contents(/home/www/web1/html/php_dev/test.txt) [function.file-put-contents]: failed to open stream: Permission denied in /home/www/web1/html/php_dev/sys/lib.activity.php (Zeile 58)
Java - Socketbasierter MultiThread Chatserver [Archiv] - PHP-Scripte PHP-Tutorials PHP-Jobs und vieles mehr
ebiz-consult PHP Entwicklung
- Ad -
php-resource




Archiv verlassen und diese Seite im Standarddesign anzeigen :
Java - Socketbasierter MultiThread Chatserver


 
ZuLtAn
31-08-2009, 02:31 
 
Hallo zusammen,

ich versuche mich gerade an einem Chatserver in Java und komme leider überhaupt nicht weiter. Der Server läuft über die ServerSocket-Klasse und soll, wie es sich für einen Chat gehört, natürlich mehrere Clients gleichzeitig bedienen. Also versuche ich das mit Threads zu lösen.

Was ich bisher habe:


/* Chatserver java */

import java.net.*;
import java.io.*;

public class ChatServer

// Anfang Attribute
// Ende Attribute

{

// Anfang Methoden
public static void main(String[] args)
{
int cnt = 0;
try {
System.out.println("Warte auf Verbindungen auf Port 4000...");
ServerSocket echod = new ServerSocket(4000);
while (true) {
Socket socket = echod.accept();
(new ChatClientThread(++cnt, socket)).start();
}
} catch (IOException e) {
System.err.println(e.toString());
System.exit(1);
}
}
// Ende Methoden
}

class ChatClientThread
extends Thread
{

// Anfang Attribute1
private int verbindungsnummer;
private Socket socket;
// Ende Attribute1


public ChatClientThread(int verbindungsnummer, Socket socket)
{
this.verbindungsnummer = verbindungsnummer;
this.socket = socket;
}

// Anfang Methoden1

public void run()
{
String msg = "Chatserver: Verbindung hergestellt";
System.out.println(msg);

try {
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
out.write((msg + "\r\n").getBytes());
int c;
while ((c = in.read()) != -1) {
out.write((char)c);
System.out.print((char)c);
}
System.out.println("Verbindung " + verbindungsnummer + " wird beendet");
socket.close();
} catch (IOException e) {
System.err.println(e.toString());
}
}
// Ende Methoden1
}


Als Client verwende ich Flash, was so eigentlich auch ganz gut funktioniert.
Mein Problem ist, das mit diesem Script bisher zwar beliebig viele Clients auf dem Server einloggen können, aber der Server eher als Echo-Server fungiert, da er jedem Client nur das gesendete wieder zurücksendet und eben auch nur dem der gesendet hat...nicht gerade sehr sinnvoll :)

Ich wollte nun die Sockets in einem array speichern und dann nacheinander jedem Clienten die eingehenden Messages senden, aber irgendwie klappt das nicht. Sobald ich irgendwie die im try-block der run()-Methode etwas verändere, kann ich weder senden noch empfangen.

Ich möchte jetzt eigentlich nur, das der Client identifiziert wird (er sendet beim Verbindungsaufbau eine Kennung - seinen Usernamen) und das er in einer Liste gespeichert wird, damit ich dann eine Art Clientpool verwalten kann...Ich hab es auch schon mit der Vector-Klasse probiert...ohne grossen Erfolg.

Ich muss dazu sagen, das ich noch nicht allzu bewandert bin was Java betrifft und daher meine Schwierigkeiten habe.

Ich wäre dankbar, wenn mir mal jemand etwas auf die Sprünge helfen könnte...ich habe schon so ziemlich das ganze Wochenende damit verbracht, aber bin immer nur mit Fehlern belohnt worden...

Gruß

 
onemorenerd
31-08-2009, 11:45 
 
Ohne synchronized wird das nichts. Google das mal!

http://www.acm.org/crossroads/xrds6-1/ovp61.html

 
ZuLtAn
31-08-2009, 13:01 
 
Super, das hilft enorm, danke dir :) So langsam nimmt es gestalt an ....
Im Code bei dem Link gibt es allerdings ein entscheidendes Problem: der Server wirft eine NullPointerException in Zeile 66 aus und die wird auch nicht aufgefangen, wenn der Client die Verbindung nicht mit "/Quit" beendet. Das ist aber ja nicht immer möglich, z.B. bei einem Verbindungsabbruch...Wieso fängt IOException ioe dies nicht auf und wie oder an welcher Stelle kann man das ändern ??

Gruss

 
onemorenerd
31-08-2009, 13:17 
 
Welche ist denn Zeile 66, ich habe keine Lust zu zählen. Außerdem wäre es besser, wenn du deinen Code postest. Der sieht ja sicherlich schon nicht mehr so aus wie auf der verlinkten Seite.

 
ZuLtAn
31-08-2009, 14:04 
 
Ok, also dies ist mal meine ChatHandler Klasse, jetzt ist die Zeile der Exception allerdings 75, da ich ja was verändert habe. Es ist aber immer die While-Schleife, in der die Nachrichten an alle Clienten gesendet werden.


class ChatHandler extends Thread {
static Vector handlers = new Vector( 10000 );
private boolean registered = false;
private String username;
private Socket socket;
private BufferedReader in;
private PrintWriter out;

public ChatHandler(Socket socket) throws IOException {
this.socket = socket;
in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(
new OutputStreamWriter(socket.getOutputStream()));
}
public void run() {
String line;

synchronized(handlers) {
handlers.addElement(this);
// add() not found in Vector class
}
try {
if (registered == false){
username=in.readLine();
out.println("Angemeldet als "+username);
out.flush();
registered=true;
}
while(!(line = in.readLine()).equalsIgnoreCase("/quit")) { // Dies ist Zeile 75
for(int i = 0; i < handlers.size(); i++) {
synchronized(handlers) {
ChatHandler handler =
(ChatHandler)handlers.elementAt(i);
handler.out.println(username+": "+line + "\r");
handler.out.flush();
}
}
}
} catch(IOException ioe) {
ioe.printStackTrace();
} finally {
try {
in.close();
out.close();
socket.close();
} catch(IOException ioe) {
} finally {
synchronized(handlers) {
handlers.removeElement(this);
}
}
}
}
}


Der Server läuft allerdings problemlos weiter, alle anderen Clients können normal weiter kommunizieren und es können sich auch nach der Exception weiterhin neue Clients anmelden...

Der genaue Fehler lautet (wird auch nur in der Konsole angezeigt und nicht an die Clienten weitergegeben):

Exception in thread "Thread-0" java.lang.NullPointerException at ChatHandler.run<ChatServer.java:75>

Ich hab zuerst gedacht, das es evtl. diese Zeile ist,die die Exception auswirft...ist aber nicht der Fall:


...
} catch(IOException ioe) {
ioe.printStackTrace();
} finally {
...

- -

Alle Zeitangaben in WEZ +2. Es ist jetzt 04:17 Uhr.