Sitter och försöker få igång en server och klient mellan två datorer. Servern tar emot flera anslutningar (clients). Det jag vill är att när en klient skickar ett meddelande till servern ska detta meddelande skickas ut till _alla_ klienter, inte bara till den som skickade.
Såhär ser min Server och ServerThreadklass ut.
package theGames.Piemageddon;
import java.net.*;
import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Server extends Thread {
private ServerSocket serverSocket = null;
private boolean listening = true;
@Override
public void run() {
try {
serverSocket = new ServerSocket(4444);
while (listening) {
new ServerThread(serverSocket.accept()).start();
}
serverSocket.close();
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public class ServerThread extends Thread {
private Socket socket = null;
String serverOut = "test";
public ServerThread(Socket socket) {
super("ServerThread");
this.socket = socket;
}
@Override
public void run() {
try {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
String inputLine = null;
System.out.println("Server started.");
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
out.println(inputLine);
}
out.close();
in.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Och såhär ser min ClientRead och ClientWrite ut.
package theGames.Piemageddon;
import java.io.*;
import java.net.*;
public class ClientRead implements Runnable {
private String fromServer;
private BufferedReader in;
private Thread readThread;
public ClientRead(Socket socket) {
//skapa ny tr�d
readThread = new Thread(this);
//�ppna upp l�sare av inputstreamen
try {
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (Exception e) {
System.err.println(e.getMessage());
}
//starta tr�den
readThread.start();
}
public String returnData(){
return fromServer;
}
public void run() {
try {
while (true) {
fromServer = in.readLine();
System.out.println("Server: " + fromServer);
returnData();
if (fromServer.equals("Bye.")) {
break;
}
}
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
}
}
}
public class ClientWrite implements Runnable {
private PrintWriter out;
private String guiMSG;
private Thread writeThread;
public ClientWrite(Socket socket, String guiMSG) {
try {
//Skapar outputstream fr att skicka data till server
out = new PrintWriter(socket.getOutputStream(), true);
//vad som ska skickas till servern
this.guiMSG = guiMSG;
} catch (Exception e) {
System.err.println(e.getMessage());
}
// Öppnar upp tråden
writeThread = new Thread(this);
writeThread.start();
}
public void run() {
//skickar meddelandet till servern
out.println(guiMSG);
}
}
Vore guld värt om någon kunde komma med förslag på hur jag ska lösa det!
Tack!
Vore guld värt om någon kunde komma med förslag på hur jag ska lösa det!
Tack!
Det går att lösa på flera olika sätt, en variant är att låta Server-klassen hålla en lista med alla öppna klient-sockets:
private ArrayList<Socket> sockets = new ArrayList<Socket>();
....
while (listening) {
Socket socket = serverSocket.accept();
sockets.add(socket);
...
}
och sedan göra en metod - writeToAll(String msg) - som går igenom listan och skriver till alla sockets som inte är stängda.
private ArrayList<Socket> sockets = new ArrayList<Socket>();
protected synchronized void writeToAll(String message) {
ListIterator<Socket> i = sockets.listIterator();
while (i.hasNext()) {
Socket socket = i.next();
if (!socket.isClosed()) {
try {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println(message);
} catch(IOException e) {
}
} else {
i.remove();
}
}
}
Gör om konstruktorn på ServerThread så att det tar en referens till Server och skicka med det när du skapar en ny ServerThread, så att din ServerThread kan anropa writeToAll():
Sen anropar du writeToAll istället för att skriva till den enskilda socketens output-ström:
server.writeToAll(inputLine);
Det du behöver göra är att finslipa det hela lite, lägga till hantering för att plocka bort socketar som stängs ur listan (nu tas de bort om de är stängda i writeToAll) och kanske inte skapa en ny PrintWriter varje gång listan itereras utan istället skapa det initialt.