ObjectOutputStream方法writeObject在android上挂起

时间:2011-11-17 15:16:37

标签: java android sockets stream java-server

我写了一些客户端 - 服务器通信。

我的服务器:

public class Server {


    public synchronized static void sendPacket(Packet packet,
            ObjectOutputStream server) {

        try {
            server.writeObject(packet);
            server.flush();
        } catch (IOException e) {
            Log.d(TAG, "Error while sending a packet. Output stream is unaviable.");
        }
    }

    public synchronized static Packet readPacket(ObjectInputStream sourceStream) {
        Packet recivedPacket = null;
        try {
            recivedPacket = (Packet) sourceStream.readObject();
        } catch (StreamCorruptedException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
    } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        return recivedPacket;
    }


    /** Register user on the server */
    private User registerUser(Socket socket) {
        ClientUserLoginPacket newUserPacket = null;
        ObjectInputStream ois = null;
        ObjectOutputStream oos = null;
        try {
            Log.i(TAG, "Opening output stream...");
            oos = new ObjectOutputStream(socket.getOutputStream());
            if (oos != null)
                Log.d(TAG, "Output stream opened");

            Log.i(TAG, "Opening input stream...");
            ois = new ObjectInputStream(socket.getInputStream());
            if (ois != null)
                Log.d(TAG, "Input stream opened");

        } catch (StreamCorruptedException e1) {
                Log.e(TAG, "Error while opening stream");
        } catch (IOException e1) {
            e1.printStackTrace();
        }

        // First packet MUST be register request
        try {
            Log.d(TAG, "Waiting for login packet from client...");
            newUserPacket = (ClientUserLoginPacket) readPacket(ois);
            Log.d(TAG, "Login packet from recived...");
        } catch (Exception e) {
            Log.e(TAG, "Can't recive login packet.");
        }
        User newUserInstance = null;
        // TODO check if exists. or to map in the future
        if (newUserPacket != null) {
            newUserInstance = new User(socket, ois, oos, newUserPacket.nick);
            users.add(newUserInstance);
            Log.d(TAG, "User " + newUserPacket.nick + " registered.");

            Server.sendPacket(new ServerLoginAcceptedPacket(), oos);
            Log.d(TAG, "User accept confirmation sent.");
        }
        return newUserInstance;
    }
    @Override
        public void run() {

            Log.i(TAG, "Starting server...");
            ServerSocket server;
            try {
                server = new ServerSocket(PORT);
                Log.i(TAG, "Server started.");
                server.setSoTimeout(0);

                while (true) {
                    Log.i(TAG, "Waiting for players...");
                    final Socket socket = server.accept();
                    Log.i(TAG, "New player connected.");
                    new Thread(new Runnable() {

                        @Override
                        public void run() {
                            Log.i(TAG, "Try to register new player.");
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                            User user = registerUser(socket);
                            while (true) {

                                Log.i(TAG, "Waiting for packets from " + user.nick+"...");
                                Packet packet = readPacket(user.ois);
                                Log.i(TAG, "Packet from " + user.nick + " recived.");

                                if (packet instanceof ...) {
                                     ...
                                }
                            }
                        }

                    }).start();
                    }

            } catch (IOException e) {
                Log.i(TAG, "Port is busy.");
            }

        }


    private class User {
        public Socket connection;
        public ObjectInputStream ois;
        public ObjectOutputStream oos;
        public String nick;
        public boolean inGame;

        public User(Socket socket, ObjectInputStream ois,
                ObjectOutputStream oos, String nick) {
            this.connection = socket;
            this.ois = ois;
            this.oos = oos;
            this.nick = nick;
    }
    // ...
}

我的客户:

public class Client {
    callbackHandler = new Thread(new Runnable() {

        @Override
        public void run() {

            while (true) {

                Log.e(TAG, "Waiting for incomeing packets...");
                Packet packet = (Packet) Server.readPacket(serverInput);
                Log.e(TAG, "Packet recived.");

                if (packet instanceof ServerLoginAcceptedPacket) {
                    Log.e(TAG, "Recived packet is "
                            + packet.getClass().toString());
                    Intent intent = new Intent(MyActivity.this,
                            MainMenuActivity.class);

                    MyActivity.this.startActivity(intent);
                }
            }

        }
    });


    public void connectToServer() {

        SocketAddress sockaddr = new InetSocketAddress(mEditTextIp.getText()
                .toString(), Server.PORT);
        server = new Socket();
        try {
            server.setSoTimeout(1000);
            Log.d(TAG, "Connecting to server.");
            server.connect(sockaddr, Server.PORT);
            Log.d(TAG, "Connected to server.");
        } catch (IOException e) {
            Log.e(TAG, "Can't connect to server.");
            server = null;
        }

        if (server != null)
            try {
                server.setSoTimeout(0);
                Log.d(TAG, "Opening output stream...");
                serverOutput = new ObjectOutputStream(server.getOutputStream());
                if (serverOutput != null)
                    Log.d(TAG, "Output stream opened");
                else
                    Log.e(TAG, "Error while opening output stream");

            } catch (IOException e) {
                Log.e(TAG, "Server socket probably closed");
            }
    }

    public void requestLogin() {

        new Thread(new Runnable() {

            @Override
            public void run() {
                Log.e(TAG, "Sending login packet...");
                Server.sendPacket(new ClientUserLoginPacket(mEditTextLogin
                        .getText().toString(), ""), serverOutput); // TODO send
                                                                    // pass and
                                                                    // email
                Log.e(TAG, "Login packet send");
            }
        }).start();
    }

    public void authenticate(View v) {

        if (server == null)
            connectToServer();

        if (server != null) {

            requestLogin();

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            try {
                serverInput = new ObjectInputStream(server.getInputStream());
            } catch (StreamCorruptedException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (serverInput != null) {

                Log.e(TAG, "Start reciving callbacks...");
                callbackHandler.start();
            } else {
                Log.d(TAG, "Can't open input stream to server.");
            }
        }

    }

    public void runServer(View v) {
        new Thread(new Server()).start();

            Toast.makeText(this, "Server running...", 1000).show();
    }
}

使用按钮触发runServer()authenticate()功能。

问题是,在服务器重新启动ClientLoginPacket之后,所有后续sentPacket函数都会挂起oos.writeObject()

我认为从/向流读/写的顺序可能是错误的。 打开流并将对象写入它们的正确顺序应该是什么? 在打开ObjectOutputStream之前,我是否必须向ObjectInputStream写一些内容?

1 个答案:

答案 0 :(得分:0)

几个小时后,我发现方法synchronizedreadPacket()之前的关键字sendPacket()存在问题。 ;)