我做一个简单的, 没有线程 客户端 - 服务器 进行GUI有两个一个按钮程序 服务器 和 客户 端。当 客户端 按下按钮时,它将按钮上的文本更改为 “ C” 并发送到 服务器 “ C” 字符串,因此 服务器 端的按钮将文本更改为 “ C” 。 服务器的 工作方式与 客户端 相似,但是发送的是 “ S” 而不是 “ C” 。他们轮流工作:轮到 客户时 , 服务器 客户端 始终首先启动。
当 客户 机按钮,它工作正常,但是当 服务器 按下按钮,它改变了按钮, “S” 的 服务器 端而不是在 客户 端。我知道我做错了。
服务器代码:
public class Serv implements ActionListener { private JButton button; private boolean myTurn; private ServerSocket sock; private Socket s; private BufferedReader input; private PrintStream output; public Serv() throws UnknownHostException, IOException { button = new JButton(); myTurn = false; sock = new ServerSocket(9001); s = null; button = new JButton(); } public void createGUI() { JFrame frame = new JFrame("TicTacToe - Server"); JPanel mainPanel = new JPanel(); mainPanel.setPreferredSize(new Dimension(100, 100)); button = new JButton(""); button.setPreferredSize(new Dimension(100, 100)); button.setFont(new Font(button.getFont().getName(), button.getFont().getStyle(), 70)); button.setActionCommand("1"); button.addActionListener(this); mainPanel.add(button); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(mainPanel); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } public void startMyGame() throws IOException { createGUI(); s = sock.accept(); input = new BufferedReader(new InputStreamReader(s.getInputStream())); output = new PrintStream(s.getOutputStream(), true); while(true) { if(myTurn == false) { myTurn = true; String out = input.readLine(); button.setText(out); } } } public static void main(String args[]) { Serv tc = null; try { tc = new Serv(); tc.startMyGame(); } catch(Exception ex) { ex.printStackTrace(); } finally { try { tc.close(); } catch(Exception ex) { ex.printStackTrace(); } } } private void close() throws IOException { this.sock.close(); this.input.close(); this.output.close(); } @Override public void actionPerformed(ActionEvent e) { if(myTurn == true) { if(e.getActionCommand().equals("1")) { JButton b = (JButton) e.getSource(); b.setText("S"); output.println("S"); myTurn = false; } } } }
客户代码:
public class Cli implements ActionListener { private JButton button; private boolean myTurn; private Socket sock; private BufferedReader input; private PrintStream output; public Cli() throws UnknownHostException, IOException { button = new JButton(); myTurn = true; sock = new Socket("127.0.0.1", 9001); input = new BufferedReader(new InputStreamReader(sock.getInputStream())); output = new PrintStream(sock.getOutputStream(), true); } public void createGUI() { JFrame frame = new JFrame("TicTacToe - Client"); JPanel mainPanel = new JPanel(); mainPanel.setPreferredSize(new Dimension(100, 100)); button = new JButton(""); button.setPreferredSize(new Dimension(100, 100)); button.setFont(new Font(button.getFont().getName(), button.getFont().getStyle(), 70)); button.setActionCommand("1"); button.addActionListener(this); mainPanel.add(button); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(mainPanel); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } public void startMyGame() throws IOException { createGUI(); while(true) { if(myTurn == false) { myTurn = true; String out = input.readLine(); button.setText(out); } } } private void close() throws IOException { this.sock.close(); this.input.close(); this.output.close(); } public static void main(String args[]) { Cli tc = null; try { tc = new Cli(); tc.startMyGame(); } catch(Exception ex) { ex.printStackTrace(); } finally { try { tc.close(); } catch(Exception ex) { ex.printStackTrace(); } } } @Override public void actionPerformed(ActionEvent e) { if(myTurn == true) { if(e.getActionCommand().equals("1")) { JButton b = (JButton) e.getSource(); if(!b.getText().equals("X") || !b.getText().equals("O")) { b.setText("C"); output.println("C"); myTurn = false; } } } } }
我已删除导入,因此代码会更短。
您的代码当前存在的问题:
正在研究更干净的示例…
例如:
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(); } }