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



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

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

我的问题是:

  1. 客户端在不等待输入的情况下继续代码流
  2. 服务器端似乎卡在了某条线路上,我重新设置了连接

这是客户端的代码:

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 null nullIE——在我点击登录屏幕上的"登录"之前,客户端到达login.getUsername方法。

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

java.net.SocketException:服务器中ObjectInputStream ois = new ObjectInputStream(client.getInputStream());行的连接重置。

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

以下是如何修复第一个问题(第二个问题我看不到你的代码,所以我帮不上忙),你需要一种同步主线程和UI的方法。

因此,首先让AWT event dispatching thread启动您的UI作为下一个:

SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
login.open();
}
});

或者,如果你使用Java 8,简单地说:

SwingUtilities.invokeLater(() -> login.open());

然后让你的主线程在get方法之前等待,让它调用一个新方法,如下所示:

login.waitForInputs();
String name = login.getUsername();
...

然后,在类LoginScreen中,新方法只需执行以下操作即可使调用线程等待:

public void waitForInputs() throws InterruptedException {
synchronized (this) {
// Make the current thread waits until a notify or an interrupt
wait();
}
}

最后,您需要修改方法actionPerformed,以便在正常情况下释放主线程,方法如下:

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中获取输入值。

相关内容

最新更新