1

I've implemented a Java TCP server running on my PC which will accept incoming messages sent from an Android device running the client, also implemented. The server just receives the messages from the Android device and sends back an answer. Everything works fine until I try to send a second message from the Android device: then, the app crashes!

But I don't know why. I use a button to send the message previously written.

This is the server thread code (the thread is simply called from main using run()):

public class ServerThread extends Thread {
        ServerSocket serverSocket;

        public ServerThread() {
        }

        public void run() {
            String incomingMsg;

            try {
                System.out.println("Starting socket thread...");

                serverSocket = new ServerSocket(21111);

                System.out
                        .println("ServerSocket created, waiting for incomming connections...");

                Socket socket = serverSocket.accept();

                BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
                        socket.getOutputStream()));
                BufferedReader in = new BufferedReader(new InputStreamReader(
                        socket.getInputStream()));

                while (true) {
                    // System.out.println("Connection accepted, reading...");

                    while ((incomingMsg = in.readLine()) != null && socket.isConnected()) {
                        System.out.println("Message recieved: " + incomingMsg
                                + ". Answering...");

                        // send a message
                        String outgoingMsg = "Message \"" + incomingMsg
                                + "\" recieved on server."
                                + System.getProperty("line.separator");
                        out.write(outgoingMsg);
                        out.flush();

                        System.out.println("Message sent: " + outgoingMsg);
                    }

                    if (socket.isConnected()) System.out.println("Socket still connected");
                    else System.out.println("Socket not connected");
                }

            } catch (Exception e) {
                System.out.println("Error: " + e.getMessage());
                e.printStackTrace();
            }

        }
    }

And this is the client code. I'm using AsyncTask:

public class MainActivity extends Activity {
    private static final String TAG = "MainActivity";

    private Button sendButton;
    private EditText messageText;
    private String messageToSend;
    private ClientSender clientSender;
    private Context context;
    private Socket socket;

    private static String SERVER_IP = "192.168.1.129";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        messageText = (EditText) findViewById(R.id.editTextMessage);
        sendButton = (Button) findViewById(R.id.sendButton);
        context = this.getApplicationContext();
        clientSender = new ClientSender(context);
        socket = null;

        sendButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                messageToSend = messageText.getText().toString()
                        + System.getProperty("line.separator");

                clientSender.execute(messageToSend);

            }
        });

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    private class ClientSender extends AsyncTask<String, Void, Socket> {
        private Socket socket;
        private String answer;
        private Context context;
        private BufferedWriter out;
        private BufferedReader in;

        public ClientSender(Context context) {
            this.context = context;
            socket = null;
            out = null;
            in = null;
        }

        @Override
        protected Socket doInBackground(String... params) {
            try {
                if (socket == null) {
                    socket = new Socket(SERVER_IP, 21111);

                    out = new BufferedWriter(
                            new OutputStreamWriter(socket.getOutputStream()));
                    in = new BufferedReader(
                            new InputStreamReader(socket.getInputStream()));
                }

                out.write(params[0]);
                out.flush();

                answer = in.readLine() + System.getProperty("line.separator");

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

            return socket;
        }

        protected void onPostExecute(Socket socket) {
            if (socket != null) {
                Toast.makeText(context, answer, Toast.LENGTH_LONG).show();

            } else {
                Toast.makeText(context, "Can't connect to server!",
                        Toast.LENGTH_LONG).show();
            }

        }

    }

}

I don't know what's going on, but I suspect there may be something wrong with the socket connection.

4
  • please show us the stack trace from the crash Commented May 11, 2013 at 14:11
  • I'm executing the client on a real device Commented May 11, 2013 at 14:14
  • Normally plugging a cable into your PC allows you to get logcat. Consider using ACRA if it doesn't. Commented May 11, 2013 at 14:50
  • Okey, the second time I push the Send button, there seems to be an exceptiong going: java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once) Commented May 11, 2013 at 15:51

2 Answers 2

1

Change your button's onClick listener so that it creates a new ClientSender each time;

public void onClick(View v) {
   messageToSend = messageText.getText().toString() + System.getProperty("line.separator");
   new ClientSender(Activity.this).execute(messageToSend);
}
Sign up to request clarification or add additional context in comments.

Comments

0

Based on just a quick look, I'd guess you need to remove the line:

clientSender = new ClientSender(context);

from your onClick() method.

1 Comment

Thanks for the answer. I tried something to fix it before and forgot to remove that line I removed it... but still doesn't work!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.