首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用ObjectInputStream而不是BufferedReader时获取BufferedReader

使用ObjectInputStream而不是BufferedReader时获取BufferedReader
EN

Stack Overflow用户
提问于 2015-07-22 21:15:21
回答 1查看 1.7K关注 0票数 0

我正在尝试建立一个连接到一个套接字服务器,它使用对象流进行读写。我能够将对象发送到服务器,但是当我尝试使用ObjectInputStream侦听响应时,我会得到一个错误。

注意: debug.debug()是围绕sout的包装器。

我的当事人:

代码语言:javascript
复制
public class Client {

    ObjectInputStream in;
    ObjectOutputStream out;

    Debug debug = new Debug();

    /**
     * Connect to a local socket server and start IO streams
     * @param port Port to connect to
     */
    public void connect(Integer port) {

        try{
            Socket socket = new Socket("localhost", port);
            debug.debug("CONNECTED", "GREEN");

            in = new ObjectInputStream(socket.getInputStream());
            out = new ObjectOutputStream(socket.getOutputStream());

            while (true) {
                try {
                    handleResponse(in.readObject());
                } catch (IOException e) {
                    debug.debug("CONNECTION_LOST", "ERROR");
                    break;
                }
            }
            connect(8080);
        } catch (Exception e) {
            debug.debug("Could not connect to host", "ERROR");
            try {
                Thread.sleep(3000);
                connect(8080);
            } catch (InterruptedException ex) {
                debug.debug("Sleep failed", "ERROR");
            }
        }
    }

    public void out(Model model) {

        try {
            out.reset();
            out.writeObject(model);
            debug.debug("Sent serialized object to server. [" + model.model + "]");
        } catch (IOException e) {
            debug.debug("Could not write object", "ERROR");
        }
    }

    private void handleResponse(Object model) {

        if (model instanceof User)
            if (((User)model).authorized)
//                ((User)model).dispatch();
                debug.debug("accepted");
    }

    public void main(String[] args) throws InterruptedException {

        connect(8080);
    }
}

登录类:

代码语言:javascript
复制
public final class Login extends JComponent implements Dispatcher {

    Button login;
    TextField email;
    PasswordField password;

    User User = new User();

    Debug debug = new Debug();

    public Login() {

        setLayout(new GridBagLayout());

        login = new Button("LOGIN", null);
        email = new TextField();
        password = new PasswordField();

        login.addActionListener(e -> {
            if (!email.getText().equals(""))
                if (!password.getText().equals("")) {
                    User.email = email.getText();
                    User.password = password.getText();
                    Admin.Socket.out(User);
                }
        });

        build();
    }

    public void userAuthorized() {

        debug.debug("authorized");
    }

    public void build() {

        GridBagConstraints constraint = new GridBagConstraints();

        constraint.anchor = GridBagConstraints.PAGE_START;
        constraint.gridx = 0;
        constraint.gridy = 0;
        constraint.gridheight = 1;
        constraint.gridwidth = 2;

        constraint.ipadx = 250;
        add(email, constraint);
        constraint.insets = new Insets(10, 0, 0, 0);
        constraint.gridy = 1;
        add(password, constraint);
        constraint.gridy = 2;
        constraint.ipadx = 100;
        constraint.ipady = 15;
        add(login, constraint);
    }
}

当我调用out方法时,这给了我一个java.lang.NullPointerException。但是,如果我使用BufferedReader来侦听,那么一切都会像预期的那样工作。

代码语言:javascript
复制
    public void connect(Integer port) {

        try{
            Socket socket = new Socket("localhost", port);
            debug.debug("CONNECTED", "GREEN");

            // BufferedReader instead of ObjectInputStream
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            out = new ObjectOutputStream(socket.getOutputStream());

            while (true) {
                try {
//                    handleResponse(in.readObject());
                    debug.debug(in.readLine());
                } catch (IOException e) {
                    debug.debug("CONNECTION_LOST", "ERROR");
                    break;
                }
            }
            connect(8080);
        } catch (Exception e) {
            debug.debug("Could not connect to host", "ERROR");
            try {
                Thread.sleep(3000);
                connect(8080);
            } catch (InterruptedException ex) {
                debug.debug("Sleep failed", "ERROR");
            }
        }
    }

当我调用时,服务器接收发送的对象。但是,现在我无法侦听服务器返回的对象。我做错了什么?

编辑堆栈跟踪:

代码语言:javascript
复制
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at socket.Client.out(Client.java:59)
    at applications.admin.components.Login.lambda$new$0(Login.java:48)
    at applications.admin.components.Login$$Lambda$6/500977346.actionPerformed(Unknown Source)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2346)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
    at java.awt.Component.processMouseEvent(Component.java:6527)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
    at java.awt.Component.processEvent(Component.java:6292)
    at java.awt.Container.processEvent(Container.java:2234)
    at java.awt.Component.dispatchEventImpl(Component.java:4883)
    at java.awt.Container.dispatchEventImpl(Container.java:2292)
    at java.awt.Component.dispatchEvent(Component.java:4705)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4898)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4533)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4462)
    at java.awt.Container.dispatchEventImpl(Container.java:2278)
    at java.awt.Window.dispatchEventImpl(Window.java:2739)
    at java.awt.Component.dispatchEvent(Component.java:4705)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:746)
    at java.awt.EventQueue.access$400(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:697)
    at java.awt.EventQueue$3.run(EventQueue.java:691)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:86)
    at java.awt.EventQueue$4.run(EventQueue.java:719)
    at java.awt.EventQueue$4.run(EventQueue.java:717)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:716)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

编辑服务器:

代码语言:javascript
复制
public class Server {

    static Debug debug = new Debug();

    /**
     * Start a socket server
     */
    public void listen(Integer port, TextArea logs) {

        logs = logs != null ? logs : new TextArea();

        try {
            ServerSocket server = new ServerSocket(port);
            debug.debug("Server is running", "GREEN", logs);

            while (true) {
                Handler handler;
                try {
                    handler = new Handler(server.accept(), logs);
                    Thread client = new Thread(handler);
                    client.start();
                } catch (IOException e) {
                    debug.debug("CLIENT_ACCEPT Failed", "ERROR", logs);
                    System.exit(-1);
                }
            }

        } catch (IOException e) {
            debug.debug("SERVER_START Failed", "ERROR", logs);
        }
    }

    public void main(String[] args) throws InterruptedException {

        listen(8080, null);
    }
}

处理程序:

代码语言:javascript
复制
public class Handler implements Runnable {

    Socket client;
    Debug debug = new Debug();

    ObjectInputStream in;
    ObjectOutputStream out;

    TextArea logs;

    User user = new User();

    /**
     * Client instance running on new thread
     *
     * @param client Client Socket
     */
    Handler(Socket client, TextArea logs) {

        this.client = client;
        this.logs = logs;
        debug.debug("CLIENT_CONNECTED", "GREEN", logs);
    }

    /**
     * Listen to the client Stream and respond
     */
    @Override
    public void run() {

        try {
            in = new ObjectInputStream(client.getInputStream());
            out = new ObjectOutputStream(client.getOutputStream());

            while (true) {
                try {
                    try {
                        handleResponse((User) in.readObject());
                    } catch (ClassNotFoundException e) {
                        debug.debug("Unable to read object", "ERROR", logs);
                    }
                } catch (IOException e) {
                    debug.debug("CLIENT_DISCONNECTED", "ERROR", logs);
                    break;
                }
            }
        } catch (IOException e) {
            debug.debug("CONNECTION_FAILED", "ERROR", logs);
        }
    }

    private void handleResponse(User user) {

        debug.debug("Received serialized object from client. [" + user.model + "]", logs);

        if (user.auth()) {
            try {
                out.reset();
                out.writeObject(user);
                debug.debug("server: AUTHORIZED", "GREEN", logs);
            } catch (IOException e) {
                debug.debug("Couldn't write object", "ERROR", logs);
            }
        } else {
            debug.debug("server: UNAUTHORIZED", "ERROR", logs);
        }
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-07-23 01:14:50

还不清楚ClientLogin类是如何连接的,所以我来猜猜。

ObjectInputStream构造函数,如javadoc中所述,“将被阻塞,直到相应的ObjectOutputStream编写和刷新了标题”。因此,您的Client.connect()线程冻结在in = new ObjectInputStream(...)行,并且不为inout设置值。(实际上,服务器线程也是出于同样的原因冻结的,所以您有一个死锁。)同时,Login线程试图向out写一些东西,但是out仍然是null,所以它得到了一个NullPointerException

为什么BufferedReader不会发生这种情况呢?它不会阻塞构造函数,所以线程只是继续执行,为out设置非out值,每个人都很高兴。

修复:首先创建ObjectOutputStream并刷新它,这样另一端的ObjectInputStream就不需要等待了。换句话说,改变

代码语言:javascript
复制
in = new ObjectInputStream(socket.getInputStream());
out = new ObjectOutputStream(socket.getOutputStream());

代码语言:javascript
复制
out = new ObjectOutputStream(socket.getOutputStream());
out.flush();
in = new ObjectInputStream(socket.getInputStream());

在客户端和服务器上。

另一个问题是,Client.out字段不是volatile,而且没有明显的同步,所以即使在Client.connect()线程中out设置为非null值之后,Login线程也可能在那里看到null。因此,我建议您将Client.out字段设置为volatile (也可能是Client.in )。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31574111

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档