Search code examples
javaandroiddebuggingclient-serverobjectinputstream

ObjectInputStream haults program


I am trying to send an ArrayList to a client on an android device. The server says it sent the object however on the android device it hangs. I have read around that when creating an ObjectInputStream, an ObjectOuputStream must be created first and then flushed. I have tried that however this is not working for me. I didn't post the code for getting the clients as its just simply reading from a textfile. The Client class is very basic with few properties such as username, password and friends arraylist of strings. Any help would be much appreciated. Server:

public class Server {
     private static final int port = 9001;
     private static final String IPAddr = "xxxxxxxxxxx";
     ServerSocket server = null;
     ArrayList <Client> users = new ArrayList<Client>();


     public Server(){           
        try{
            server = new ServerSocket(port);
            System.out.println("connected server on port" + port);
            while(true){
                System.out.println("waiting for connection my ip add is "+ InetAddress.getLocalHost().getHostAddress());
                Socket clientsocket = server.accept();
                System.out.println("Connect to client:"+ clientsocket.getInetAddress().getHostName());
                ClientThread client = new ClientThread(clientsocket);
                client.start();
            }
        } catch(IOException e) {
            System.err.println("Could not listen on port");
        }
     }


//Thread     
    public class ClientThread extends Thread {
        private Socket sckt = null;

        public ClientThread(Socket sckt){
            super("ClientThread");
            this.sckt = sckt;
        }
        public void run(){
        try{    
            PrintWriter out = new PrintWriter(sckt.getOutputStream(), true);
            BufferedReader input = new BufferedReader(new InputStreamReader(sckt.getInputStream()));
            ObjectOutputStream objectOutput = new ObjectOutputStream(sckt.getOutputStream());
            objectOutput.flush();

            String Username = input.readLine();
            String Password = input.readLine();
            System.out.println("recieved from client: "+ Username);
            int ClientIndex = isClient(Username);
            if (ClientIndex != -1){
                if(users.get(ClientIndex).password.equals(Password)){
                    //password correct  -> send friends
                    out.println("correct");
                    out.flush();
                    System.out.println(Username + " is correct");
                    LoadClientFriends(Username, ClientIndex);

                    objectOutput.writeObject(users.get(ClientIndex).Friends);
                    System.out.println("Friends sent");
                } else {
                    //password incorrect -> retry
                    out.println("password");
                    System.out.println(Username + " has wrong password");

                }


            } else {
                //not a registered client 
                out.println("wrong");
                System.out.println(Username + " is not a client");
            }
        } catch(Exception e){
            System.err.println("Couldnt connect to Client socket");
        }
        }
    }

    public static void main(String[] args){
        Server svr = new Server();
    }
}

Client/Android:

public class MainActivity extends ActionBarActivity {
//Varibles
    EditText username;
    EditText password ;
     private static final int port = 9001;
     private static final String IPAddr = "xxxxxxx";
//Methods

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fragment_main);
      /*  Drawable d = getResources().getDrawable(R.drawable.actionbar_background);
        getActionBar().setBackgroundDrawable(d);*/
    }
    public void Login(View view) {
        //connect to server 

         Thread myThread2 = new Thread(Connect);
         myThread2.start();

    }

    public void Register(View view) {

            Intent i = new Intent(this, register_screen.class);
            startActivity(i);

    }      
    Runnable Connect = new Runnable()
    {
        public void run()
        {
            try {

                Socket connection = new Socket(IPAddr,port);

                BufferedReader input = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                PrintWriter output = new PrintWriter(connection.getOutputStream(), true);


                //Sent the username a password for verifaction

                username = (EditText)findViewById(R.id.edtName);
                password = (EditText)findViewById(R.id.edtPassword);

                output.println(username.getText().toString());
                output.flush();
                output.println(password.getText().toString());
                output.flush();

                //Receive confirmation of client
                String res = input.readLine();

                if (res.contains("correct")){
                    ObjectOutputStream objectOutput = new ObjectOutputStream(connection.getOutputStream());
                    objectOutput.flush();
                    ObjectInputStream objectInput = new ObjectInputStream(new BufferedInputStream(connection.getInputStream())); //Error Line!

                    Object object = objectInput.readObject();
                    ArrayList<String> friends =  (ArrayList<String>) object;
                    Intent intent = new Intent(MainActivity.this,chat_screen.class);
                    intent.putExtra("Friends", friends);
                    startActivity(intent);

                }else if (res.contains("password")){

                    Intent i = new Intent(getBaseContext(), MainActivity.class);
                    startActivity(i);

                }else {


                }


            }catch (Exception e){


            }
            }

     };
}

Solution

  • The error you see is due to multiple output stream format. Stick to either ObjectOutputStream/ObjectInputStream or PrintWriter/BufferedReader. I suggest ObjectOutputStream/ObjectInputStream.

    Server code: Use objectOutPut for all writes.

    // out.println("correct");
    objectOutput.writeUTF("correct");
    
    // Update code for password and wrong too - Use objectOutput.writeUTF("");
    

    Client code: Use just ObjectInputStream instead of BufferedReader

    Define the objectInput here instead:

    // BufferedReader input = new BufferedReader(new InputStreamReader(connection.getInputStream()));
    ObjectInputStream objectInput = new ObjectInputStream(connection.getInputStream());
    PrintWriter output = new PrintWriter(connection.getOutputStream(), true);
    
    // Read data as follows:    
    // String res = input.readLine();
    String res = objectInput.readUTF();