ServletException
ServletException

Reputation: 239

Handle Java Socket connection between 2 JFrames

I'm trying to create a client/server application using sockets, I have 2 JFrames (2 seperate classes) , a user will initially open up the one frame and there's a button to go to the other JFrame, when clicked it disposes the previous frame and opens the new frame.

I'd like to know how I could switch back and forth between these 2 JFrames without my program crashing and needing to forcefully close, I am establishing the connection in the constructor of each JFrame.

try {
    server = new Socket("localhost", PORT);
     
    // creates & instantiates objectInput and output streams
    getStreams();
} catch (IOException ex) {
      System.out.println("error creating socket: " + ex.getMessage());
}

I have these in the constructor of both JFrames


EDIT

Server

public class Testserver {

    private ServerSocket serverSocket;
    private Socket client;
    private final int PORT = 5432;
    private ObjectOutputStream objectOutputStream;
    private ObjectInputStream objectInputStream;

    public Testserver() {
        try {
            serverSocket = new ServerSocket(PORT);
        } catch (IOException ex) {
            JOptionPane.showMessageDialog(null, "Error: " + ex.getMessage());
            System.out.println("error creating server socket: " + ex.getMessage());
        }
    }

    private void listenForClient() {

        try {
            System.out.println("Server is running and is waiting/listening for a connection to be established.");
            ////JOptionPane.showMessageDialog(null, "Server is running and is waiting/listening for a connection to be established." );
            client = serverSocket.accept();
            System.out.println("A client has connected");

            objectOutputStream = new ObjectOutputStream(client.getOutputStream());
            objectInputStream = new ObjectInputStream(client.getInputStream());
            processClient();
        } catch (IOException ex) {
            JOptionPane.showMessageDialog(null, "Error: " + ex.getMessage());
        }

    }
    
    
    private void processClient() {

        do {
            try {
                String messageFromClient = (String) objectInputStream.readObject();
                
                // check for clients requests and handle them (database etc)
                System.out.println("[CLIENT] " + messageFromClient);

            } catch (IOException ex) {
                Logger.getLogger(Testserver.class.getName()).log(Level.SEVERE, null, ex);
                break;
            } catch (ClassNotFoundException ex) {
                Logger.getLogger(Testserver.class.getName()).log(Level.SEVERE, null, ex);
                break;
            }

        } while (true);
        
        closeConnections();

    }
    
    
    private void closeConnections() {
        try {
            objectInputStream.close();
            objectInputStream.close();
            client.close();
        } catch (IOException ex) {
            JOptionPane.showMessageDialog(null, "Error: " + ex.getMessage());
        }
    }


    public static void main(String[] args) {
        new Testserver().listenForClient();
    }
}

CustomerGUI


public class CustomerGUI extends JFrame implements ActionListener{
    
    private Socket server;
    private ObjectOutputStream objectOutputStream;
    private ObjectInputStream objectInputStream;
    private JPanel panel1;
    private JButton btnAdminGUI;
    private final int PORT = 5432;
    
    public CustomerGUI() {
        
        btnAdminGUI = new JButton("Go to Admin GUI");
               
        try {
            server = new Socket("localhost", PORT);
            System.out.println("Connected to server");
            
            objectOutputStream = new ObjectOutputStream(server.getOutputStream());
            objectInputStream = new ObjectInputStream(server.getInputStream());
            
            objectOutputStream.writeObject("from Customer");
            objectOutputStream.flush();

        } catch (IOException ex) {
            JOptionPane.showMessageDialog(null, "Error: " + ex.getMessage()););
        }
        
        btnAdminGUI.addActionListener(this);

    }
    
    
    public void setGUI() {
        
        
        add(btnAdminGUI);
        setSize(300, 400);
        setVisible(true);
    }

    public static void main(String[] args) {
        new CustomerGUI().setGUI();
        
    }

    @Override
    public void actionPerformed(ActionEvent e) {
       if(e.getSource() == btnAdminGUI) {
           new AdminGUI().setGUI();
           dispose();
       }
    }
}


AdminGUI

public class AdminGUI extends JFrame implements ActionListener{
    
    private Socket server;
    private ObjectOutputStream objectOutputStream;
    private ObjectInputStream objectInputStream;
    private JPanel panel1;
    private JButton btnCustomerGUI;
    private final int PORT = 5432;
    
    public AdminGUI() {
        
        btnCustomerGUI = new JButton("Go to Customer GUI");
               
        try {
            server = new Socket("localhost", PORT);
            System.out.println("Connected to server");
            
            objectOutputStream = new ObjectOutputStream(server.getOutputStream());
            objectInputStream = new ObjectInputStream(server.getInputStream());
            
            objectOutputStream.writeObject("from Admin");
            objectOutputStream.flush();

        } catch (IOException ex) {
            JOptionPane.showMessageDialog(null, "Error: " + ex.getMessage());
        }
        
        btnCustomerGUI.addActionListener(this);

    }
    
    
    public void setGUI() {
        
        
        add(btnCustomerGUI);
        setSize(300, 400);
        setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
       if(e.getSource() == btnCustomerGUI) {
           new CustomerGUI().setGUI();
           dispose();
       }
    }
}

Upvotes: 0

Views: 107

Answers (1)

matt
matt

Reputation: 12346

I'll post a solution this because I have done something similar recently, but I don't have a UI for it yet.

The idea is MVC, with two models, a Server and Client and there are two Views, JPanels, which can be displayed in a window/jframe/dialog, whichever is appropriate. The Controller is essentially an api for interacting with the model, for this simple example the controllers will be mixed with the models. I think this example has a lot of flaws, but I think it gives a good idea of what needs to be done.

A button starts a course of action,

serverControls.addActionListener( evt ->{ } );

The button does one of two actions, either it starts the server or it stops the server.

serverLoop.submit( ()->{
    server.listen();
    //should notify a listener that the server has stopped.
});

serverLoop is another thread of execution, server.listen() is a long running task. It shouldn't return until we want the server to stop listening.

The other button is on the client. It has a similar structure..

 clientControls.addActionListener( evt->{
            clientLoop.submit( () -> client.connect( server ) );
            clientLoop.submit( 
                () -> SwingUtilities.invokeLater( 
                    () -> response.setText( client.communicate() )
                ) 
            );
        });

First the client is going to connect, then it communicates.

import javax.swing.*;
import java.util.concurrent.*;

public class ClientServerApp{
    
    static class Server{
        volatile boolean available = false;
        public void listen(){
            try{
                available = true;
                synchronized( this ){
                    wait(5000);
                }
            } catch(Exception e){
                e.printStackTrace();
                //if the server terminates unexpectedly.
            }finally{
                available = false;
            }
        }
        public void stopListening(){
            
        }
    }
    
    static class Client{
        Server connected;
        public void connect(Server host){
            connected = host;
        }
        
        public String communicate(){
            
            if(connected != null){
                if(connected.available){
                    return "connected";
                } else{
                    return "cannot connect";
                }
            }
            return "no host";
        }            
    }
    
    public static void main(String[] args){
            Server server = new Server();
            Client client = new Client();
            
            ExecutorService serverLoop = Executors.newSingleThreadExecutor();
            JPanel serverView = new JPanel();
            JButton serverControls = new JButton("start");
            serverView.add( serverControls );
            
            serverControls.addActionListener( evt ->{
                if(serverControls.getText().equals("start") ){
                    serverControls.setText("stop");
                    serverLoop.submit( ()->{
                        server.listen();
                        //should notify a listener that the server has stopped.
                    });
                } else{
                    server.stopListening();
                    serverLoop.submit( ()->{
                        //will be run after the listen loop has completed. 
                        SwingUtilities.invokeLater( () - >
                            serverControls.setText("start") 
                        );
                    });
                }
            } );
            
            JPanel clientView = new JPanel();
            JButton clientControls = new JButton("connect");
            JTextField response = new JTextField(40);
            clientView.add( clientControls );
            clientView.add(response);
            
            ExecutorService clientLoop = Executors.newSingleThreadExecutor();
            System.out.println("creating client action listener");
            clientControls.addActionListener( evt->{
                clientLoop.submit( () -> client.connect( server ) );
                clientLoop.submit( () -> 
                    SwingUtilities.invokeLater( 
                        () -> response.setText( client.communicate() ) 
                    ) 
                );
            });
            
            JFrame mainWindow = new JFrame();
            mainWindow.setContentPane( serverView);
            mainWindow.pack();
            mainWindow.setVisible(true);
            
            JDialog clientWindow = new JDialog( mainWindow, "Client Window");
            clientWindow.setContentPane(clientView);
            clientWindow.pack();
            clientWindow.setVisible(true);
            
    }
    
}

In a more complete example, you would probably have a Listener interface, so that your swing gui can response to changes in state of the server or the client, and a controller that manages the threads.

Upvotes: 1

Related Questions