0

I have made an application that opens up a socket via a thread and updates based on what is typed. Here is the code:

Server.java:

public class Server {
    public static void main(String[] args) throws IOException {
        int portNumber = 2392;

        boolean listening = true;

        System.out.println("Server: Running...");

        try (ServerSocket serverSocket = new ServerSocket(portNumber)) {
            System.out.println("Server: Connected to Client!");
            while (listening) {
                new ServerThread(serverSocket.accept()).start();
            }
        } catch (IOException e) {
            System.out.println("Exception caught when trying to listen on port "
                + portNumber + " or listening for a connection( '" + e.getMessage() + "' );");
        } finally {

            System.out.println("Server: Disconnecting...");
        }
    }
}

Server Thread.java:

public class ServerThread extends Thread  {
    private Socket socket = null;
    Scanner reader = new Scanner(System.in);

    public ServerThread(Socket socket) {
        super("ServerThread");
        this.socket = socket;
    }

    public void run() {
        System.out.println("Ruasd");

        try (PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
            String outputLine = "";
            while (!outputLine.equals("Disconnect")) {
                outputLine = reader.nextLine();
                out.println(outputLine);
            }
            socket.close();
            reader.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Client.java:

public class MainActivity extends Activity {

    private Socket socket;
    private TextView status;

    private BufferedReader in;
    private Handler mHandler;

    private static final int SERVERPORT = 2392;
    private static final String SERVER_IP = "...ip#...";


    @Override
    protected void onCreate(Bundle bundle) {
        super.onCreate(bundle);

        setContentView(R.layout.activity_vitals);
        status = (TextView) findViewById(R.id.text_status);

        new Thread(new CommunicationThread()).start();
    }

    @Override
    protected void onStop() {
        super.onStop();

        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

class CommunicationThread implements Runnable {
    @Override
    public void run() {
        try {
            InetAddress serverAddr = InetAddress.getByName(SERVER_IP);

            socket = new Socket(serverAddr, SERVERPORT);
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            while (true) {
               final String fromServer = in.readLine();
               System.out.println("Server: " + fromServer);

                MainActivity.this.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        // This code will always run on the UI thread, therefore is safe to modify UI elements.
                        status.setText(fromServer);
                    }
                });

                if (fromServer.equals("Disconnect."))
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

It works perfectly the first time and outputs to the status TextView correctly. However, when I restart the application, it outputs every other word. For instance, If I type "Hey" "Hi "You" "How", I will see "Hi" and "How" in the TextView the second time I start the application.

What's really odd to me is that when I do System.out.println("Server: " + fromServer) it is outputting all values. Any suggestions are greatly appreciated.

Danielson
  • 2,605
  • 2
  • 28
  • 51
Zack
  • 871
  • 10
  • 24
  • The fact that you are getting the data from the server correctly implies this is a GUI related issue. – Olavi Mustanoja Oct 24 '14 at 06:49
  • @OlaviMustanoja That's what I thought as well but I've been debugging for hours and have yet to come up with a reason as to why it is acting strange when setting the text value in the TextView. – Zack Oct 24 '14 at 06:53
  • when you call the setText, can you also output the fromServer output from the called method? Particularly, can you output the correct text to stdout from the same place where the actual gui change should take place? – Olavi Mustanoja Oct 24 '14 at 06:56
  • @OlaviMustanoja do you mean adding the System.out.println() to the runOnUIThread? – Zack Oct 24 '14 at 12:14
  • Ah, yes, that's what I meant. I was running on low caffeine earlier :) – Olavi Mustanoja Oct 24 '14 at 12:21
  • @OlaviMustanoja I KO'd so I wasn't able to respond until this morning lol! Alright I did as requested. As it turns out, it is only outputting every other time as suggested from the output on the screen. I also noticed that it seems to get worst the more times that I close and reopen. (Outputs every 3 times). I'm not sure why but it's now acting the same outside the UIthread. I will edit and post both the server and client code for you to look at. – Zack Oct 24 '14 at 13:05
  • @OlaviMustanoja it seems to be also incrementing by how many ServerThreads I create. For instance, if I close and reopen the app 3 times. It will most likely output to text every 3 times. – Zack Oct 24 '14 at 13:18
  • You have a peculiar way of starting a new serversocket. I can't determine whether or not it is actually the cause of your issues. I'll test your code as I get home in 15 minutes. Also in ServerThread's while loop you should break if outputLine is null. Try it. – Olavi Mustanoja Oct 24 '14 at 13:33
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/63596/discussion-between-zack-and-olavi-mustanoja). – Zack Oct 24 '14 at 15:33

1 Answers1

0

Ok I think I found the problem (got it working for me, that is). In your CommunicationThread, you didn't have a while loop. Also, you need to iterate the server's input until it is null. See below:

class CommunicationThread implements Runnable {
    @Override
    public void run() {
        try {
            // keep the connection alive.
            while (true) {
                InetAddress serverAddr = InetAddress.getByName(SERVER_IP);

                socket = new Socket(serverAddr, SERVERPORT);
                BufferedReader in = new BufferedReader(
                    new InputStreamReader(socket.getInputStream()));

                String fromServer;
                // get server messages until there are none
                while ((fromServer = in.readLine()) != null) {

                    System.out.println("Server: " + fromServer);

                    MainActivity.this.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            // This code will always run on the UI thread, therefore is safe to modify UI elements.
                            status.setText(fromServer);
                        }
                    });

                    if (fromServer.equals("Disconnect."))
                        break;

                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Please get back to me on how it works out :)

Olavi Mustanoja
  • 2,045
  • 2
  • 23
  • 34
  • I am getting an error from the variable "fromServer" when calling setText(): "Variable 'fromServer' is accessed from within inner class, needs to be final" – Zack Oct 24 '14 at 15:06
  • @Zack you could do `final String text = fromServer; status.setText(text);` where the variable `text` is outside the runnable inner class. – Olavi Mustanoja Oct 24 '14 at 15:24
  • I created a private data member and was storing the value in there. I tried running the program though but it still does not work. The way google glass works is that the onStop() method is called when the card is dismissed (I think it is different than with a phone). – Zack Oct 24 '14 at 15:30
  • Here lets move this to chat: http://chat.stackoverflow.com/rooms/63596/discussion-between-zack-and-olavi-mustanoja – Zack Oct 24 '14 at 15:34