Jeroen Vannevel
Jeroen Vannevel

Reputation: 44439

Application hangs when attempting to retrieve text from an inputstream

Situation

I've been creating a program to exchange messages between two computers in the LAN. One computer identifies itself as the server while the other is a client. Upon startup, the user has to enter the Host and the Port of another computer, should he wish to connect as a client to that machine. The setup of how it works is very basic: You type your message, hit enter and it shows up on your own screen. After that your conversation partner has to click a button to retrieve the latest messages and it should show up on his screen. This goes on untill someone leaves.

Problem

The program launches correctly and asks for the connection settings. After that I initiate the connection on both computers and things seem to go fine (after the connection is established, a label shows you what your status, e.g. Client or Server, is (1)). Things continue looking fine when I enter a message and send it, the output gets written to the sender's screen and no unexpected behaviour occurs.

When I want to retrieve the messages on the other computer, the program completely freezes. No objects in the GUI are clickable and no output is shown.

Code

Assuming the connection is correctly established (see (1)), I will outline the process of sending a message below while leaving out the non-essential parts.

GuiApplication.java

private void sendMessage() {
    connection.sendMessage(message);
    showMessage(message);
}

Connection.java
public void sendMessage(String message) {
    if (isClient()) {
        client.sendMessage(message);
    } else if (isServer()) {
        server.sendMessage(message);
    }
}

Client.java
public void sendMessage(String message) {
    outbound = new PrintWriter(socket.getOutputStream(), true); // Defined outside this method
    outbound.println(message);
}

The process of sending a message is pretty straightforward, but I wanted to include it just in case I've overlooked something.

What follows is the code I've created to retrieve the new messages. The concept is simple: I check if there are any new messages and if there are, I retrieve them.

GuiApplication.java
if (connection.hasNewMessage()) {
    message = connection.retrieveMessage();
}
showMessage(message);

The first part (connection.hasNewMessage()) will check whether or not the program is either running the client or the server and call the appropriate retrieveMessage().

Client.java
public String retrieveMessage() throws IOException {
    inbound = socket.getInputStream(); // Defined outside this method
    return IOUtils.toString(inbound, "UTF-8");
}

At first I've tried this with a BufferedReader using an InputStreamReader and calling the readLine() method, but decided to try out the commons.io method once I noticed it didn't work (the same problem as I am currently facing).

Question

It's been made pretty clear by now: why does my program hang the moment I click a button which retrieves new messages?

External

I'm not sure if it's frowned upon, but here's the github repository in case you wanted a better overview, although I believe the necessary code snippers are there.

Upvotes: 0

Views: 144

Answers (2)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285403

I did look at your code, and as I suspected, your problem has absolutely nothing to do with the code you've posted. Your GUI completely ignores Swing threading rules, and calls long-running tasks on the main Swing event thread known as the Event Dispatch Thread or EDT. Since this thread is responsible for all Swing drawing and user interaction, your GUI is prevented from doing this and becomes completely frozen.

Please read Concurrency in Swing for the details on this.

And next time, please post an sscce so we don't have to dive into a huge amount of your source code! The key to the SSCCE is to eliminate all code not essential to your problem at hand. This is not easy to do and will require a lot of work from you to create, so that it has enough code to run, but not too much as to drown us in code, but then you are asking volunteers to help you on their free time, so it's not asking too much.

Best of luck!

Upvotes: 2

AlexR
AlexR

Reputation: 115328

Without reading all your explanations and all code attachments I can assume that you are reading from or writing to stream into UI thread (e.g. call IO operation from Action or ActionListener directly and you are blocked on read/write.

Please examine your code. I believe you will find point where you call to in.read() or out.write(). Add print just before and just after the line. You will see that you never exit read or write.

This is because the other side does not perform opposite operation. So, you have to:

  1. decouple UI from IO. IO must be done in separate thread.
  2. check why other side blocks your flow.

Upvotes: 2

Related Questions