【问题标题】:Java networking in server-client model服务器-客户端模型中的 Java 网络
【发布时间】:2013-05-04 04:47:36
【问题描述】:

我有一个关于使用服务器-客户端模型在网络中等待消息的问题。

您可以将收到的消息区分为两种不同的类型:

  1. 即席消息,例如“用户已登录”,与客户端中的任何其他内容无关。

  2. 响应消息,例如当您自己尝试登录时。

我的问题是关于后者,即我使用这个方案:

  1. 向服务器发送登录请求(以“登录用户名密码加密”的形式)

  2. (客户端)等待服务器响应或发生五秒超时。

  3. (服务器)以“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();
    }
}

我使用同步,但我不太喜欢它,所以如果可能的话我想避免它。 然而问题在于网络在不同的线程中运行,并且响应可能随时出现,但是登录过程只有五秒钟的时间需要响应。

无需联网即可重写代码:

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()); 之后的网络开头。

所以再次重复主要问题:我怎样才能使网络类(一个从服务器读取响应并处理它们的类)只在给定超时时间对“登录确认”和“登录拒绝”做出反应给定时刻,并将事件重定向到给定的 LoginProcedure 对象?

【问题讨论】:

    标签: java client-server


    【解决方案1】:

    我会以启用同步/异步消息传递系统的方式设计它。

    • 每条可交换消息都必须有一个 UUID 和一个“originID”属性。
    • 异步消息只是从发射器发送到接收器。
    • 同步消息将其内容发送到接收方,并进入“等待回复”队列。调用者线程暂停,或不时对队列执行 ping 操作。
    • 接收方解析原始消息,准备回复并使用原始消息的 ID 填充 originID 属性。
    • 回复消息被发送到发射器。
    • 发射器对其进行解析,识别出这是一个回复,并向“等待回复”队列发出信号。
    • 原始线程被允许继续进行,而答复在手。
    • 如果没有收到回复,则可能会引发 TimeOutException。

    【讨论】:

      猜你喜欢
      • 2012-04-26
      • 1970-01-01
      • 2011-02-10
      • 1970-01-01
      • 1970-01-01
      • 2011-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多