I\'m making a simple, no thread Client-Server program where GUI has one button on both server and client side. When clie
Current issues with your code:
Working on a cleaner example.......
For example:
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import javax.swing.*;
public class SimpleServerClient {
private static final int PORT = 9001;
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
try {
SimpleServer server = new SimpleServer(PORT, "Server", false);
SimpleClient client = new SimpleClient(PORT, "Client", true);
server.createGui();
client.createGui();
} catch (IOException e) {
e.printStackTrace();
}
});
}
}
interface SimpleGui {
void sendLine(String nextLine);
}
// background thread handles listening to the Scanner
// which scans a Socket's InputStream
class MyWorker extends SwingWorker<Void, Void> {
public static final String LINE = "line";
private Scanner inputScanner;
private SimpleGui gui;
private String line = "";
public MyWorker(Scanner inputScanner, SimpleGui gui) {
this.inputScanner = inputScanner;
this.gui = gui;
}
@Override
protected Void doInBackground() throws Exception {
while (inputScanner.hasNext()) {
// get line from Scanner
// use the setter method in case we want to use a PropertyChangeListener later
setLine(inputScanner.nextLine());
// send line to the GUI
gui.sendLine(getLine());
}
return null;
}
public String getLine() {
return line;
}
// again rigged up to allow use of PropertyChangeListeners
public void setLine(String line) {
this.line = line;
firePropertyChange(LINE, null, line);
}
}
// code that both the client and server GUI classes share
abstract class DefaultGui implements SimpleGui {
// this guy ***must**** be volitile!
private volatile boolean myTurn;
protected Scanner inputScanner;
protected PrintStream out;
protected JButton button = new JButton("Blank");
protected Socket socket;
protected String name;
protected int port;
public DefaultGui(int port, String name, boolean myTurn) {
this.port = port;
this.name = name;
this.myTurn = myTurn;
}
@Override
public void sendLine(String nextLine) {
button.setText(nextLine);
myTurn = true;
}
public void createGui() {
button.addActionListener(e -> actionPerformed(e));
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(300, 300));
panel.add(button);
JFrame frame = new JFrame(getName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
protected void actionPerformed(ActionEvent e) {
if (!myTurn) {
return;
}
out.println(getName());
button.setText(getName());
myTurn = false;
}
public String getName() {
return name;
}
}
class SimpleServer extends DefaultGui {
private ServerSocket serverSocket;
public SimpleServer(int port, String name, boolean myTurn) throws IOException {
super(port, name, myTurn);
serverSocket = new ServerSocket(port);
new Thread(() -> {
try {
// accept() blocks the current thread, so must be called on a background thread
socket = serverSocket.accept();
inputScanner = new Scanner(socket.getInputStream());
out = new PrintStream(socket.getOutputStream(), true);
new MyWorker(inputScanner, this).execute();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
}
class SimpleClient extends DefaultGui {
public SimpleClient(int port, String name, boolean myTurn) throws IOException {
super(port, name, myTurn);
socket = new Socket("localhost", port);
inputScanner = new Scanner(socket.getInputStream());
out = new PrintStream(socket.getOutputStream());
new MyWorker(inputScanner, this).execute();
}
}