webForumDet fria alternativet

Server & Client

2 svar · 501 visningar · startad av Melea

MeleaMedlem sedan juli 20033 147 inlägg
#1

Hejsan.

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!

sgtpepperMedlem sedan apr. 20007 588 inlägg
#2

Melea skrev:

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():

public ServerThread(Server server, Socket socket) {
    	super("ServerThread");
    	this.socket = socket;
    	this.server = server;
    }
  new ServerThread(this, socket).start();

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.

MeleaMedlem sedan juli 20033 147 inlägg
#3

Skickar över en virtuellt flak med finöl, tack! :bire

130 ms totalt · 3 externa anrop · v20260731065814-full.3292ce1b
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
127 ms — hämta tråd, inlägg och bilagor (db)