ObjectInputStream.readBoolean()无法正常读取

时间:2018-03-12 02:59:21

标签: java stream network-programming

我正在尝试制作聊天应用程序。在下面的代码中,我正在尝试实现用户注册功能,但是我遇到了ObjectInputStream.readBoolean()的问题。基本上,客户端程序提示用户输入用户名和密码,以注册新用户或以现有用户身份登录。数据被发送到服务器,服务器根据用户列表验证数据(实际上是HashMap)。然后,服务器将告诉客户端信息是否有效(由布尔isUserValid表示)。我希望客户端再次提示信息是否无效,所以我有一个while (true)并在信息有效时中断。但是,似乎客户端没有正确接收布尔值isUserValid。当isUserValid为真时,它可以正常工作......

以下是ChatClient的代码:

import javax.swing.*;
import java.io.*;
import java.net.*;
import java.util.*;

public class ChatClient implements Runnable {

    public static final int PORT = 1234;

    private Socket client;
    private ObjectInputStream input;
    private ObjectOutputStream output;
    ...

    @Override
    public void run() {
        ...
        boolean isRegistering = JOptionPane.showOptionDialog(null, "Log in or register?", "", JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE, null, new String[]{"Log in", "Register"}, null) == 1;
        try {
            // Let the server know that the client wants to register.
            output.writeBoolean(isRegistering);
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }

        // This will repeatedly prompt the user if the entered info is not valid.
        // Invalid user info can be duplicate usernames while registering, or if the password is invalid.
        while (true) {
            try {
                // I need to generalize this to Object[] because one element is a String while the other is a char[].
                // I know this is not good practice, but how else can I do it?
                Object[] userInfo;
                if (isRegistering) {
                    // The difference between registration dialog and login dialog is only word choice.
                    userInfo = Dialogs.registrationDialog();
                } else {
                    userInfo = Dialogs.loginDialog();
                }
                output.writeObject(userInfo);

                // Break out of the cycle of prompts if the user is valid.
                // For some reason this works when the user is valid, but fails to read a boolean if the server writes false.
                // For example, if I first register username "fdsa" password "123", then the registration is successful,
                // but then if I register "fdsa" "456", the registration is unsuccessful, and the server writes false.
                // The client should then loop again and show another registration dialog, but apparently input.readBoolean()
                // does not receive the false boolean.
                if (input.readBoolean()) break;
            } catch (IOException e) {
                e.printStackTrace();
                System.exit(1);
            }
        }
    }

    public static void main(String[] args) {
        new Thread(new ChatClient()).run();
    }
}

服务器代码:

import java.io.*;
import java.net.*;
import java.util.*;

public class IncomingClientHandler implements Runnable {
    private List<Message> messageList;
    private Socket client;
    private ObjectOutputStream output;
    private ObjectInputStream input;
    private Map<String, char[]> usersList;

    public IncomingClientHandler(List<Message> l, Map<String, char[]> u, Socket c) {
        usersList = u;
        messageList = l;
        client = c;
        try {
            output = new ObjectOutputStream(c.getOutputStream());
            input = new ObjectInputStream(c.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        System.out.println("New client accepted at " + client.getInetAddress());
        try {
            boolean isRegistering = input.readBoolean();
            Object[] userInfo;
            while (true) {
                try {
                    userInfo = (Object[]) input.readObject();
                    boolean isUserValid;
                    if (isRegistering) {
                        // The user will not be valid if the same username is already registered.
                        isUserValid = !usersList.containsKey(userInfo[0]);
                    } else {
                        try {
                            // The user will not be valid if the password doesn't match.
                            isUserValid = Arrays.equals(usersList.get(userInfo[0]), (char[]) userInfo[1]);
                        } catch (NullPointerException e) {
                            isUserValid = false;
                        }
                    }
                    System.out.println("The entered user info is " + (isUserValid ? "valid." : "invalid."));
                    output.writeBoolean(isUserValid);
                    if (isUserValid) break;
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }    
            if (isRegistering) {
                usersList.put((String) userInfo[0], (char[]) userInfo[1]);
            }
            ...
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 }

我遗漏了很多我认为与我的问题无关的代码,但是如果你想要完整的项目,它也是on Github.

0 个答案:

没有答案