Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使客户端等待输入,客户端-服务器_Java_User Interface_Server_Client - Fatal编程技术网

Java 使客户端等待输入,客户端-服务器

Java 使客户端等待输入,客户端-服务器,java,user-interface,server,client,Java,User Interface,Server,Client,我正在尝试编写一个非常简单的客户机-服务器程序 基本上,只要客户机连接到服务器,他就会得到一个登录屏幕,在那里他必须输入用户名、密码和文件名 我的问题是: 客户端继续执行代码流,而不实际等待输入 服务器端似乎卡在了某条线路上,我重新设置了连接 这是客户端的代码: public static void main(java.lang.String[] args) throws JsonIOException, JsonSyntaxException, ClassNotFoundException,

我正在尝试编写一个非常简单的客户机-服务器程序

基本上,只要客户机连接到服务器,他就会得到一个登录屏幕,在那里他必须输入用户名、密码和文件名

我的问题是:

  • 客户端继续执行代码流,而不实际等待输入
  • 服务器端似乎卡在了某条线路上,我重新设置了连接
  • 这是客户端的代码:

    public static void main(java.lang.String[] args) throws JsonIOException, JsonSyntaxException, ClassNotFoundException, IOException
    {
        try
        {
            Socket socket = new Socket(InetAddress.getLocalHost(), 12345);
            LoginScreen login = new LoginScreen();
            login.open();
            String name = login.getUsername();
            String pass = login.getPassword();
            String log = login.getLogname();
            System.out.println(name + " " + pass + " " + log);
        }
    
    这是登录屏幕

    @SuppressWarnings("serial")
    public class LoginScreen extends JFrame implements ActionListener
    {
        private JTextField userText;
        private JTextField passText;
        private JTextField logText;
        private JLabel userLabel;
        private JLabel passLabel;
        private JLabel logLabel;
        private JButton loginButton;
    
        private String username;
        private String password;
        private String logname;
    
        public String getUsername()
        {
            return username;
        }
    
        public String getPassword()
        {
            return password;
        }
    
        public String getLogname()
        {
            return logname;
        }
    
        public LoginScreen()
        {
            super("Login");
    
            userLabel = new JLabel("username: ");
            passLabel = new JLabel("password: ");
            logLabel = new JLabel("File name: ");
    
            Dimension preferredSize = new Dimension(80,20);
            userText = new JTextField("");
            userText.setPreferredSize(preferredSize);
            passText = new JTextField("");
            passText.setPreferredSize(preferredSize);
            logText = new JTextField("");
            logText.setPreferredSize(preferredSize);
    
            loginButton = new JButton("Login");
            loginButton.addActionListener(this);
        }
        public void open()
        {
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setSize(500,500);
            setLayout(new BorderLayout());
    
            JPanel userPanel = new JPanel();
            userPanel.setLayout(new FlowLayout());
            add(userPanel,BorderLayout.NORTH);
    
            JPanel passPanel = new JPanel();
            passPanel.setLayout(new FlowLayout());
            add(passPanel,BorderLayout.CENTER);
    
            JPanel logPanel = new JPanel();
            logPanel.setLayout(new FlowLayout());
            add(logPanel,BorderLayout.SOUTH);
    
            JPanel loginPanel = new JPanel();
            loginPanel.setLayout(new FlowLayout());
            add(loginPanel,BorderLayout.EAST);
    
            userPanel.add(userLabel);
            userPanel.add(userText);
            passPanel.add(passLabel);
            passPanel.add(passText);
            logPanel.add(logLabel);
            logPanel.add(logText);
            loginPanel.add(loginButton);
    
            pack();
    
            this.setVisible(true);
        }
        @Override
        public void actionPerformed(ActionEvent arg0) 
        {
            username = new String(userText.getText());
            password = new String(passText.getText());
            logname = new String(logText.getText());
        }
    }
    
    这是服务器

    try 
    {
        Socket client = socket.accept();
        ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());
        ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
        String userPassFile = (String)ois.readObject();
        String[] parts = userPassFile.split("");
        if(AuthenticationManager.Authenticate(parts[0], parts[1]))
        {
            new MMULogService(client,parts[2]);
        }
        else
        {
            oos.writeObject("Incorrect Username / Password");
        }
        client.close();
    } 
    
    应该注意的是,在执行客户端之前,我打开了服务器。 当前输出是
    null
    IE-客户端在我单击登录屏幕上的“login”之前到达login.getUsername方法

    一旦我关闭登录屏幕,我就会得到错误-

    java.net.SocketException:在
    ObjectInputStream ois=new ObjectInputStream(client.getInputStream())行重置连接


    如何让客户端在执行get方法之前等待我实际点击登录按钮?如何修复连接重置错误?

    以下是如何修复第一个问题(第二个问题我看不到您的代码,因此无法帮助),您需要一种方法来同步主线程和UI

    因此,首先让
    AWT事件调度线程
    启动您的UI,作为下一步:

    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            login.open();
        }
    });
    
    或者,如果您使用Java 8,只需:

    SwingUtilities.invokeLater(() -> login.open());
    
    然后让主线程在get方法之前等待,方法如下:

    login.waitForInputs();
    String name = login.getUsername();
    ...
    
    public void actionPerformed(ActionEvent arg0)
    {
        username = userText.getText();
        password = passText.getText();
        logname = logText.getText();
        // Here you should test if the input values are OK if it is KO do a   
        // return to prevent calling the following code
        synchronized (this) {
            // Release the waiting threads
            notifyAll();
        }
    }
    
    然后在类
    LoginScreen
    中,新方法将通过执行以下操作使调用线程等待:

    public void waitForInputs() throws InterruptedException {
        synchronized (this) {
            // Make the current thread waits until a notify or an interrupt
            wait();
        }
    }
    
    最后,您需要修改方法
    actionPerformed
    ,以便在正常情况下释放主线程,方法如下:

    login.waitForInputs();
    String name = login.getUsername();
    ...
    
    public void actionPerformed(ActionEvent arg0)
    {
        username = userText.getText();
        password = passText.getText();
        logname = logText.getText();
        // Here you should test if the input values are OK if it is KO do a   
        // return to prevent calling the following code
        synchronized (this) {
            // Release the waiting threads
            notifyAll();
        }
    }
    

    我们已经实现了一个简单的
    wait/notify
    机制,在调用get方法之前从UI获取输入值。

    我看不出在客户端使用socket的地方?你能把剩下的代码给我看一下吗?嗨,尼古拉斯,我还没有用套接字传输数据。只是为了连接到服务器。在传输数据之前,我想检查UI(登录屏幕)是否正常工作。代码的其余部分是无关的,不包括任何客户机-服务器。谢谢,这确实解决了第一个问题。关于第二个问题,出于某种原因,服务器的操作似乎停留在ObjectInputStream ois=new ObjectInputStream(client.getInputStream());,当我在它后面打印“test”时,它什么也不做。