サーバー クライアント モデルを使用したネットワークでのメッセージの待機について質問があります。
受信したメッセージは、次の 2 つの異なるタイプで区別できます。
「ユーザーがログインしました」などのアドホック メッセージで、クライアントの他のものとは関係ありません。
たとえば、自分がログインしようとしているときの応答メッセージ。
私の質問は後者に関するものです。つまり、私はこのスキームを使用しています:
ログイン要求をサーバーに送信します (「ログイン ユーザー名 パスワード暗号化」の形式で)
(クライアント) サーバーが応答するまで、または 5 秒のタイムアウトが発生するまで待ちます。
(サーバー) 「loginconfirmed」または「logindenied」で応答します。
だから、これをコーディングする最良の方法は何だろうと思っています。ここには古いコードがありますが、ここでの結合は高すぎると思います。このコードのフレームワークの一部をすでに書き直しました (グラフィカルなクラス、これはまったく意味がなく、私はそれをすべきではありませんでした):
public void initLoginPanel() {
setLoginStatus(LoginStatus.TIMEOUT); //standard value
LoginPanelOld loginPanel = new LoginPanelOld();
int result = JOptionPane.showConfirmDialog(this, loginPanel, "Please log in", JOptionPane.OK_CANCEL_OPTION);
if (result == JOptionPane.OK_OPTION) {
String login = loginPanel.getLoginValue();
if (!login.isEmpty() && login.split(" ").length == 1) {
Network.getInstance().waitFor("loginconfirmed");
Network.getInstance().waitFor("logindenied");
Network.getInstance().send("login " + login);
initSimpleTextPanel("Logging in...");
try {
//TODO synchronize on some "login waiter object"
synchronized(this) {
wait();
}
switch (loginStatus) {
case CONFIRMED:
JOptionPane.showMessageDialog(this, "Login succesful.");
break;
case DENIED:
JOptionPane.showMessageDialog(this, "Login denied.");
initLoginPanel();
break;
case TIMEOUT:
JOptionPane.showMessageDialog(this, "Could not connect to the server.");
initLoginPanel();
break;
default:
JOptionPane.showMessageDialog(this, "An unexpected error has occured.");
initLoginPanel();
break;
}
removeAll();
revalidate();
repaint();
} catch (InterruptedException ex) {
Logger.getLogger(MainPanelOld.class.getName()).log(Level.SEVERE, null, ex);
}
}
else {
JOptionPane.showMessageDialog(this, "You have entered invalid details.");
initLoginPanel();
}
}
else if (result == JOptionPane.CANCEL_OPTION || result == JOptionPane.CLOSED_OPTION) {
initLoginPanel();
}
}
私は同期を使用していますが、あまり好きではないので、できれば避けたいと思っています。ただし、問題の種類は、ネットワークが別のスレッドで実行され、応答がいつでも来る可能性があることですが、ログイン プロセスが応答を必要とするのは 5 秒だけです。
ネットワークなしで書き直されたコード:
public class LoginProcedure implements Procedure {
private final GUI gui;
private LoginPanel loginPanel;
public LoginProcedure(final GUI gui) {
this.gui = gui;
}
@Override
public void start() {
loginPanel = new LoginPanel(this);
gui.setPanel(loginPanel);
}
@Override
public void finish() {
Controller.getInstance().finishProcedure();
}
public void tryLogin(final String username, final char[] password) {
if (username.isEmpty()) {
loginPanel.setErrorMessage("Please enter your username.");
return;
}
if (password.length == 0) {
loginPanel.setErrorMessage("Please enter your password.");
return;
}
gui.setPanel(new LoadingPanel());
}
}
新しいコードでは、gui.setPanel(new LoadingPanel());
.
もう一度主な質問を繰り返します: Networking クラス (サーバーからの応答を読み取り、それらを処理するクラス) を、特定の瞬間に特定のタイムアウトで "loginconfirmed" と "logindenied" にのみ反応させ、リダイレクトする方法を教えてください。指定された LoginProcedure オブジェクトへのイベント?