Allora.....
Nel caso di un server MultiThread l'idea è che ogni volta che esso riceve una connessione avvia un nuovo Thread che si occuperà di comunicare col client, ma questo lo sapevi già
!!
In particolare quindi il server sarà formato da 2 classi: una principale (Server.java), che accetterà le connessioni e che istanzierà la seconda classe,che estenderà un Thread,(ServerMulti.java).
Classe Server.java:
nel costruttore dovrai creare un oggetto di tipo ServerSocket che starà in ascolto ,in questo caso, sulla porta 4413
serverSocket = new ServerSocket(4413);
La parte interesante è la seguente (anche questa sta nel costruttore):
while (listening) {
try {
1: Socket socket = serverSocket.accept();
2: PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
3: BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
4: clientList.add(out);
5: new ServerMulti(out,in,socket);
for(PrintWriter o:Server.clientList) {
System.out.println(Server.clientList.indexOf(o));
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
Ogni volta che un client si collega al server creo un socket con l'istruzione alla riga 1.
Poi creo un oggetto di tipo PrintWriter ed uno di tipo BufferedReader per l'input e l'output attraverso il socket stesso, righe 2 e 3
Come attributo della classe Server mi creo un ArrayList<PrintWriter> che servirà per spedire messaggi a tutti i client:
static ArrayList<PrintWriter> clientList = new ArrayList(); (in questo caso statico per dargli visibilità da ServerMulti.java, volendo avrei potuto dichiararlo non statico e passarlo come parametro al costruttore di ServerMulti.java)
Nella riga 4 aggiungo per ogni client il PrintWriter ad esso associato dentro clientList.
Nella riga 5 creo una nuova istanza della classe ServerMulti.java passando come parametro il PrintWriter, il BufferedReader ed il socket.
Classe ServerMulti.java
Come già detto ServerMulti sarà un Thread:
public class ServerMulti extends Thread {.....}
La parte interessante è il metodo run del Thread:
public void run() {
try {
while (!fine) {
try {
String inputLine = in.readLine();
processaInput(inputLine);
} catch (Exception e) {
fine = true;
}
}
out.close();
in.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Il Thread sta sempre in ascolto di un input da parte del client a cui è associato. Quando il client invia una linea la salvo nella stringa InputLine:
String inputLine = in.readLine();
il metodo processa input stabilisce il protocollo che client e server devono utilizzare per comunicare, per esempio:
public void processaInput(String input) {
if(input.equals("#quit")) {
fine = true;
}
else {
for(PrintWriter o:Server.clientList) {
o.println(input);
}
}
}
Se il client scrive "#quit" fine viene posto a true, il while finisce e viene chiusa la connessione.
se invece il client scrive qualsiasi altra cosa (ramo else) ciclo sull'ArrayList definito in Server.java e mando ad ognuno l'input ricevuto. Così facendo quello che scrive un client verrà inviato a tutti glia altri, in particolare il messaggio tornerà anche al client che lo ha spedito.
Praticamente è una chat, inserire gli username sarebbe abbastanza semplice.
Il programmino può essere testato con telnet, oppure fai un client
Ecco i 2 file:
http://web.i2000net.it/gioperna/Server.java
http://web.i2000net.it/gioperna/ServerMulti.java