[英]Simple Client-Server program using Swing GUI
I'm making a simple, no thread Client - Server program where GUI has one button on both server and client side.我做一个简单的,没有线程客户端-在GUI对服务器和客户端的一键式服务器程序。 When client presses button it changes text on a button to "C" and sends to server "C" string, so the button on the server side changes text to "C" .
当客户端按下按钮时,它将按钮上的文本更改为"C"并发送到服务器"C"字符串,因此服务器端的按钮将文本更改为"C" 。 Server works similarly to client but sends "S" instead of "C" .
服务器的工作方式与客户端类似,但发送"S"而不是"C" 。 They work in turns: when it's the client's turn, server's button is locked and he cannot change his button.
它们轮流工作:轮到客户时,服务器的按钮被锁定,他无法更改按钮。 Client always starts first.
客户端总是先启动。
When client presses button it works fine, but when server presses button it changes button to "S" on the server side but not on client's side.当客户机按钮,它工作正常,但是当服务器按下按钮,它改变了按钮,“S”在服务器端而不是在客户端。 I know what I'm doing wrong.
我知道我做错了什么。
Server code:服务器代码:
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;
}
}
}
}
Client code:客户端代码:
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;
}
}
}
}
}
I have deleted imports so the codes would be shorter.我已经删除了导入,所以代码会更短。
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();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.