Parte Server di una chat (codice completo inside)

di il
2 risposte

Parte Server di una chat (codice completo inside)

Ho creato la parte Server di una chat ma ho parecchi dubbi.
Tutto funziona bene,solo che mi fa storcere il naso usare quei 2 metodi static in ServerSide.java
userClicksSubmit(String messages)
e
appendMessage(String text)
in GraphicSide.java.A come ho capito i metodi statici sono il male assoluto e non rispecchiano la mentalità OOP.Potrei rimediare creando un oggetto di GraphicSide.java direttamente da ServerSide.java evitando di crearlo da main.
Come posso però evitare di usare
appendMessage(String text)
in GraphicSide.java??
Vorrei anche ricevere dei consigli su come è strutturata l'applicazione (magari sto facendo errori madornali e non lo so)

ServerSide.java
public class ServerSide extends Thread {
private ServerSocket ss;
private Socket sock;
private int ID;
private static Map<Client, Integer> clientList = new HashMap<Client, Integer>();
private static PrintWriter pw;
int port;

// Main Constructor takes the port to connect to a server
// in order to chat with the clients
public ServerSide(int port) throws IOException {
    this.port = port;
    this.run();
}

@Override
public void run() {
    try {
        ss = new ServerSocket(port);
    } catch (IOException e) {
        e.printStackTrace();
    }
    receivingClients();
}

public void receivingClients() {
    while (true) {
        try {
            sock = ss.accept();
            clientList.put(new Client(sock, ID), ID);
            ID++;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
//Static method that is called every time the server's user submits a message
public static void userClicksSubmit(String messages) throws IOException {
    for (Map.Entry<Client, Integer> client : clientList.entrySet()) {
        System.out.println(messages);
        pw = new PrintWriter(client.getKey().getSock2().getOutputStream());
        pw.println(messages);
        pw.flush();
    }
}
   //////////////////////////// Receives the clients' messages ////////////////////////////
private class Client extends Thread{

    private InputStreamReader inReader;
    private BufferedReader buffReader;
    private Socket sock2;
    private PrintWriter pw2;
    private int ID;
    private String messages;

    public Client(Socket sock2, int ID) throws IOException {
        this.sock2 = sock2;
        this.ID = ID;
        this.start();
    }
    public void getMessages() throws IOException {
        inReader = new InputStreamReader(sock2.getInputStream());
        buffReader = new BufferedReader(inReader);

        while ((messages = buffReader.readLine()) != null) {
            //Static method of the Graphic Interface.It appends the messages to the textArea of the application
            GraphicSide.appendMessage(messages);
            //Send the received messages to all the clients of the map list with the exception of the sender
            for (Map.Entry<Client, Integer> client : clientList.entrySet()) {
                pw2 = new PrintWriter(client.getKey().getSock2().getOutputStream());
                if (client.getValue() != ID) {
                    pw2.println(messages);
                    pw2.flush();
                }
            }
        }
    }
    public Socket getSock2() {
        return sock2;
    }
    @Override
    public void run() {
        try {
            getMessages();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

 }

}
GraphicSide.java
public class GraphicSide extends JFrame {
private JPanel contentPane;
private static JTextField textPort;
private JTextField textId;
private JButton submit;
private int port;
private static JTextArea textArea;
private static boolean agree = false;
private  String text;
private String id;


public GraphicSide() {
    setTitle("Login of the Server");
    setResizable(false);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLocationRelativeTo(null);
    setBounds(100, 100, 250, 355);
    setVisible(true);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    setContentPane(contentPane);
    contentPane.setLayout(null);


    JLabel portName = new JLabel("Port:");
    portName.setHorizontalAlignment(SwingConstants.CENTER);
    portName.setBounds(106, 102, 46, 14);
    contentPane.add(portName);

    textPort = new JTextField();
    textPort.setHorizontalAlignment(SwingConstants.CENTER);
    textPort.setToolTipText("e.g. 81");
    textPort.setBounds(77, 127, 103, 20);
    contentPane.add(textPort);
    textPort.setColumns(10);

    JLabel idLabel = new JLabel("Id:");
    idLabel.setHorizontalAlignment(SwingConstants.CENTER);
    idLabel.setBounds(106, 174, 46, 14);
    contentPane.add(idLabel);

    textId = new JTextField();
    textId.setHorizontalAlignment(SwingConstants.CENTER);
    textId.setToolTipText("e.g. Mike");
    textId.setBounds(77, 199, 103, 20);
    contentPane.add(textId);
    textId.setColumns(10);

    submit = new JButton("Submit");
    submit.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent arg0) {
            if (textId.getText().length() == 0 || textPort.getText().length() == 0) {
                JOptionPane.showMessageDialog(null, "Compile all the fields", "Error", JOptionPane.WARNING_MESSAGE);
                return;
            }
            setVisible(false);
            try {
                id = textId.getText();
                new ChatWindow();
                agree = true;
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    });

    submit.setBounds(94, 257, 74, 23);
    contentPane.add(submit);

}

private class ChatWindow extends JFrame {
    {
        this.setTitle("Server");
        this.setSize(750, 480);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);
        this.setMinimumSize(new Dimension(750, 480));

        GridBagLayout gridBagLayout_1 = new GridBagLayout();
        gridBagLayout_1.columnWidths = new int[] { 0, 640, 70 };
        gridBagLayout_1.rowHeights = new int[] { 387, 0, 0, 41, 40 };
        gridBagLayout_1.columnWeights = new double[] { 1.0, 1.0 };
        gridBagLayout_1.rowWeights = new double[] { 1.0, 0.0, 0.0, 1.0, Double.MIN_VALUE };
        this.getContentPane().setLayout(gridBagLayout_1);

        textArea = new JTextArea();
        JScrollPane scroll = new JScrollPane(textArea);
        DefaultCaret caret = new DefaultCaret();
        caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
        textArea.setEditable(true);
        textArea.setBorder(BorderFactory.createEtchedBorder());
        GridBagConstraints gbc_textArea = new GridBagConstraints();
        gbc_textArea.gridwidth = 3;
        gbc_textArea.insets = new Insets(2, 2, 5, 2);
        gbc_textArea.fill = GridBagConstraints.BOTH;
        gbc_textArea.gridx = 0;
        gbc_textArea.gridy = 0;
        this.getContentPane().add(scroll, gbc_textArea);

        JTextField textField = new JTextField();
        textField.setBorder(BorderFactory.createEtchedBorder());
        GridBagConstraints gbc_textArea_1 = new GridBagConstraints();
        gbc_textArea_1.gridheight = 2;
        gbc_textArea_1.gridwidth = 2;
        gbc_textArea_1.fill = GridBagConstraints.BOTH;
        gbc_textArea_1.insets = new Insets(2, 2, 2, 5);
        gbc_textArea_1.gridx = 0;
        gbc_textArea_1.gridy = 3;
        this.getContentPane().add(textField, gbc_textArea_1);
        this.setVisible(true);


        JButton btnNewButton = new JButton("Send");
        btnNewButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                text = textField.getText();
                try {
                    ServerSide.userClicksSubmit(textId.getText()+" : " +text);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                textArea.append(text + '\n');
                textField.setText("");
            }
        });

        textField.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "enter");
        AbstractAction pressedAction = new AbstractAction() {

            @Override
            public void actionPerformed(ActionEvent arg0) {

                // Here you put the code that is run when you press the key
                btnNewButton.doClick();
                System.out.println("Key pessed");

            }

        };
        textField.getActionMap().put("enter", pressedAction);

        GridBagConstraints gbc_btnNewButton = new GridBagConstraints();
        gbc_btnNewButton.gridheight = 2;
        gbc_btnNewButton.gridx = 2;
        gbc_btnNewButton.gridy = 4;
        this.getContentPane().add(btnNewButton, gbc_btnNewButton);

    }
}
public static void appendMessage(String text) {
    textArea.append(text + '\n');
}

public  boolean isAgree() {
    return agree;
}

public  int getPort() {
    return port = Integer.parseInt(textPort.getText());
}

}
MainClassApp.java
import java.io.IOException;
import javax.swing.JFrame;

public class MainClassApp extends JFrame {


private static final long serialVersionUID = 1L;

public static void main(String[] args) throws IOException, InterruptedException {

    GraphicSide gs = new GraphicSide();
    //Starts the server class only after the user inserts a port and presses the submit button on the GUI 
    //application
    while (true) {
        if (gs.isAgree() == true) {
            break;
        }
    }
    new ServerSide(gs.getPort());
  }
}
Consigli,consigli,consigli

2 Risposte

  • Re: Parte Server di una chat (codice completo inside)

    Per utilizzare i due metodi statici "userClicksSubmit(String messages)" e "appendMessage(String text)" su una classe diversa da quella di appartenenza hai due possibilità:
  • Re: Parte Server di una chat (codice completo inside)

    LBProfile ha scritto:


    Per utilizzare i due metodi statici "userClicksSubmit(String messages)" e "appendMessage(String text)" su una classe diversa da quella di appartenenza hai due possibilità:
    Ciao,grazie mille per la spiegazione,purtroppo quando ho letto il messaggio avevo già modificato il codice.Mi piacerebbe sapere cosa ne pensi(tu o altri esperti del forum ):
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.ArrayList;
    
    
    public class ServerSide extends Thread {
    	private ServerSocket ss;
    	private Socket sock;
    	private int ID;
    	private static ArrayList<Client> clientList = new ArrayList<Client>();
    	private static PrintWriter pw;
    	int port;
    	private GraphicSide gs;
    
    	// Main Constructor 
    	public  ServerSide() throws IOException, InterruptedException {
    		
    		 gs = new GraphicSide();
    		// Starts the Thread  only after the user inserts a port and presses the submit button on the GUI
    		// application
    		while (true) {
    			Thread.sleep(100);
    			if (gs.isAgree()) {
    				break;
    			}
    		}
    		//Pass a the current ServerSide object to the GraphicSideClass
    		gs.setServerSide(this);
    		this.run();
    		
    	}
    
    	@Override
    	public void  run() {
    		try {
    			ss = new ServerSocket(gs.getPort());
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		receivingClients();
    	}
    
    	public void receivingClients() {
    		while (true) {
    			try {
    				sock = ss.accept();
    				clientList.add(new Client(sock, ID));
    				ID++;
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    
    	// Method that is called every time the server's user submits a
    	// message
    	public void userClicksSubmit(String messages) throws IOException {
    		for (Client client : clientList) {
    			System.out.println(messages);
    			pw = new PrintWriter(client.getSock2().getOutputStream());
    			pw.println(messages);
    			pw.flush();
    		}
    	}
    
    	//////////////////////////// Receives the clients' messages	////////////////////////////////////////////////////////
    	private class Client  {
    		
    		private InputStreamReader inReader;
    		private BufferedReader buffReader;
    		private Socket sock2;
    		private PrintWriter pw2;
    		private int ID2;		
    		private String messages;
    		
    		
    		//Hashcode for int ID2
    		@Override
    		public int hashCode() {
    			final int prime = 31;
    			int result = 1;
    			result = prime * result + getOuterType().hashCode();
    			result = prime * result + ID2;
    			return result;
    		}
    
    		@Override
    		public boolean equals(Object obj) {
    			if (this == obj)
    				return true;
    			if (obj == null)
    				return false;
    			if (getClass() != obj.getClass())
    				return false;
    			Client other = (Client) obj;
    			if (!getOuterType().equals(other.getOuterType()))
    				return false;
    			if (ID2 != other.ID2)
    				return false;
    			return true;
    		}
    
    		public Client(Socket sock1, int ID) throws IOException {
    			this.sock2 = sock1;
    			this.ID2 = ID;
    			t1.start();
    		}
    
    		public void getMessages() throws IOException {
    			inReader = new InputStreamReader(sock2.getInputStream());
    			buffReader = new BufferedReader(inReader);
    			
    			while ((messages = buffReader.readLine()) != null) {
    				// Method of the Graphic Interface.It appends the
    				// messages to the textArea of the application
    				gs.appendMessage(messages);
    				// Sends the received messages to all the clients of the Array
    				// with the exception of the sender
    				for (Client client : clientList) {
    					pw2 = new PrintWriter(client.getSock2().getOutputStream());
    					if (!this.equals(client) ) {
    						pw2.println(messages);
    						pw2.flush();
    					}
    				}
    			}
    		}
    
    		public Socket getSock2() {
    			return sock2;
    		}
    		Thread t1 = new Thread(new Runnable(){
    		
    			@Override
    			public void run() {
    				try {
    					getMessages();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		});
    
    		public int getID() {
    			return ID2;
    		}
    
    		private ServerSide getOuterType() {
    			return ServerSide.this;
    		}
    
    			
    	}
    }
    
    Ho aggiunto un setMethod in GraphicSide.java che prende un oggetto ServerSide.Ho dovuto istanziare la parte grafica direttamente nella classe server (e non da main) perchè per un motivo a me ignaro,passando l'oggetto GraphicSide alla classe ServerSide.java tramite un metodo set,ottenevo un NullPointException.Ho inoltre messo un ArrayList al posto dell'HashMap e creato un hashcode per comparare i vari ID dei clients in modo da spedire il messaggio a tutti quelli della lista senza far ritornare il messaggio inviato al mittente.
Devi accedere o registrarti per scrivere nel forum
2 risposte