当前位置: 首页 > 面试题库 >

使用Swing GUI的简单客户端-服务器程序

陈功
2023-03-14
问题内容

我做一个简单的, 没有线程 客户端 - 服务器 进行GUI有两个一个按钮程序 服务器客户 端。当 客户端
按下按钮时,它将按钮上的文本更改为 “ C” html" target="_blank">并发送到 服务器 “ 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;
                }
            }
        }
    }
}

我已删除导入,因此代码会更短。


问题答案:

您的代码当前存在的问题:

  • 你正在创建一个Swing GUI的并运行它 关闭 Swing事件分派线程或EDT的。GUI应该在事件线程 启动 以便确保所有Swing代码都可以在单个线程上运行。
  • 您有一个长时间运行的while循环,它正在进行Swing突变调用,从而更新了JButton的状态。如果此代码在Swing事件线程上运行,它将阻止/冻结GUI。应该在不是EDT的后台线程中显式调用此块,并且应按照“ Swing:并发”教程中的内容,将所有Swing调用排队到事件线程中。
  • 您在不同的线程中使用了一个非易失性布尔值,可能会导致变量在应更改时未被更改
  • 您似乎立即关闭了流,从而阻止了关注点之间的充分沟通。

正在研究更干净的示例…

例如:

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();
    }    
}


 类似资料:
  • 请你给我举一个localhost的客户端和服务器使用java nio通信的小例子?我需要了解它是如何工作的。例如1)客户端需要连接,客户端连接客户端发送“你好,我是客户端”。2)服务器接受,服务器接收来自客户端的消息,服务器响应“你好,我是服务器”3)客户端发送“你好,服务器”4)服务器发送“你好,客户端”。 我不需要服务器一次处理多个客户端,我需要了解的是客户端和服务器之间具有多个消息的连接是如

  • 我是Java的新手,我正在尝试学习线程和套接字。所以决定按照官方的java教程制作简单的客户机-服务器应用程序。我的想法很简单--服务器等待连接,如果出现,它就用新的套接字、输入和输出生成新线程。客户端->建立连接;带有套接字、输入、输出和stdIn的新线程(读取行,然后发送到服务器)。但是我的代码出了点问题(不知道为什么)。连接已经建立,没有例外。谁能解释一下为什么不工作,如何修复它?您还可以对

  • 问题内容: 我想使用asyncio协程而不是多线程来重新实现我的代码。 server.py client.py 我知道有一些适当的异步网络库可以做到这一点。但是我只想在这种情况下使用asyncio核心库,以便对其有更好的了解。 仅在处理客户端定义之前添加async关键字真是太好了……这里的一段代码似乎有效,但是我仍然对实现感到困惑。 asyncio_server.py 如何以最佳方式和使用异步aw

  • 本文向大家介绍Rust 一个简单的TCP客户端和服务器应用程序:echo,包括了Rust 一个简单的TCP客户端和服务器应用程序:echo的使用技巧和注意事项,需要的朋友参考一下 示例 以下代码基于std :: net :: TcpListener上的文档提供的示例。该服务器应用程序将侦听传入的请求并发送回所有传入的数据,从而充当“回显”服务器。客户端应用程序将发送一条小消息,并期望包含相同内容的

  • 问题内容: 我正在尝试编写一个简单的Java http客户端,该客户端仅打印出服务器响应的一行。我的问题是服务器没有响应。这是我所拥有的,正在编译并且没有明显错误地运行,只是在键入主机名(例如“ www.google.com”)后挂起: 有什么建议?请注意,这假设存在一个“ index.html”-即使为true,它仍会挂起。 问题答案: 我认为我可以通过对代码进行少量更改来重现该问题,因此现在它

  • 我正在使用TCP / IP流编写客户端服务器Java程序,我的服务器连接到oracle数据库。当客户端请求一些信息时,服务器处理查询,即返回一个包含一些行的列(例如 5)。我想将整列发送回客户端,我能够发送和接收单行数据,但不能发送和接收多行(因为表包含许多行 i,e 行)....任何帮助都是可取的