Reputation: 44439
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
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
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:
Upvotes: 2