Reputation: 239
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
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