Swing code in sockets
While the options aren't clear to me the way you described them, I will describe what is common practice.
Probably the widest adopted (enterprise system) architecture uses some kind of database as a persistence layer, a middle layer with business logic and an interface (either rich client like swing or web interface) containing the view logic.
The client only contains view state-related logic: event processing, notifications, data presentation, data binding etc. Things like data persistence, retrieval, validation are done by sending a request from the interface to the middle layer which then knows how to process the request, processes it and returns any results. This communication usually takes places in the form of web services or session bean method invocations.
Using a Java Swing GUI, how can I run a Server Socket in the background and still use the GUI?
Don't block the EDT (Event Dispatch Thread). Run the server on a Thread
. See Concurrency in Swing for more details.
Mentioned in a comment, but see also this (very much) related example of providing a Swing GUI for a server & client.
Java - Threads, Swing, and ServerSocket
You are reading from your Socket on the EDT. This means that you block it. Calling invokeLater only causes your Runnable to be executed on the EDT. You are piling two calls on the EDT, one of them being your socket.
Consider moving your socket in a SwingWorker which returns progressively the values of your Socker to the GUI.
Java - Socket Swing Application Crashes
I deleted void part and put it in the mouse listener and open and closed the connection every time I sent a message. That prevented the program crashing. Thanks for helping me realize my errors.
Passively listening on a socket for a chat application
you have got issue with Concurency in Swing, Swing GUI don't know that you running / open the
Socket
onBackground Task
,all updates to the
Swing GUI
must be done on EDT, otherwise nothing happened or you got a few exceptionshave to wrap all updates from
Background Task
(in your caseRunnable#Thread
) to theinvokeLater
for Swing GUIwhile(true){
is endless loop put thereBoolean variable
instead oftrue
, then you can to stop, start or restart whatever in your caseSocket
in the case that
send.addActionListener(new ActionListener(){
runs only once time (if user invoked byJButtons
click) then to use SwingWoker for opening Socket,SwingWorker
quite good guarantee that all output should be done on EDTdifference betweens
Runnable#Thread
andSwingWorker
is thatSwingWorker
is designated to run only once times
Java socket swingWorker running but no message received or transmitted
Here's a VERY basic example.
Basically, because you program requires asynchronous communications (that is, you need to be able to read from the socket AND write to it at the same time), you need to offload each stream to a separate thread.
The management process of this example is, well, no existent. Realistically, you should have some kind of "connection" manager that would be able to cleanly close the output and input threads so that, for example, when the user types "bye", the output thread would be able to tell the connection manager that the connection should be terminated. It would then tell the input thread to stop reading any new message and terminate...
Client
public class Client {
public static void main(String[] args) {
try {
Socket master = new Socket("localhost", 8900);
new Thread(new InputHandler(master)).start();
new Thread(new OuputHandler(master)).start();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static class InputHandler implements Runnable {
private Socket socket;
public InputHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
boolean commune = true;
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (commune) {
String text = reader.readLine();
System.out.println("\n<server> " + text);
if (text.toLowerCase().equals("bye")) {
commune = false;
}
}
} catch (Exception exp) {
exp.printStackTrace();
} finally {
try {
reader.close();
} catch (Exception e) {
}
try {
socket.close();
} catch (Exception e) {
}
}
}
}
public static class OuputHandler implements Runnable {
private Socket socket;
public OuputHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
boolean commune = true;
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
Scanner scanner = new Scanner(System.in);
while (commune) {
System.out.print("> ");
String text = scanner.nextLine();
writer.write(text);
writer.newLine();
writer.flush();
if (text.equalsIgnoreCase("bye")) {
commune = false;
}
}
} catch (Exception exp) {
exp.printStackTrace();
} finally {
try {
writer.close();
} catch (Exception e) {
}
try {
socket.close();
} catch (Exception e) {
}
}
}
}
}
Server
public class Server {
public static void main(String[] args) {
try {
ServerSocket master = new ServerSocket(8900);
Socket socket = master.accept();
new Thread(new InputHandler(socket)).start();
new Thread(new OuputHandler(socket)).start();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static class InputHandler implements Runnable {
private Socket socket;
public InputHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
boolean commune = true;
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (commune) {
String text = reader.readLine();
System.out.println("\n<client> " + text);
if (text.toLowerCase().equals("bye")) {
commune = false;
}
}
} catch (Exception exp) {
exp.printStackTrace();
} finally {
try {
reader.close();
} catch (Exception e) {
}
try {
socket.close();
} catch (Exception e) {
}
}
}
}
public static class OuputHandler implements Runnable {
private Socket socket;
public OuputHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
boolean commune = true;
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
Scanner scanner = new Scanner(System.in);
while (commune) {
System.out.print("> ");
String text = scanner.next();
writer.write(text);
writer.newLine();
writer.flush();
if (text.equalsIgnoreCase("bye")) {
commune = false;
}
}
} catch (Exception exp) {
exp.printStackTrace();
} finally {
try {
writer.close();
} catch (Exception e) {
}
try {
socket.close();
} catch (Exception e) {
}
}
}
}
}
Update (whine)
While I have your source code in front of me...
There should very, very, rarely be a need to do textMessage.addKeyListener(this)
Because you are using a JTextField
, you should be using a ActionListener
instead. There are a a number of important reasons for this, but for you, the main one would be the fact that a "accept" action is Look and Feel dependent. While most systems do use Enter as there "accept" action, is not a guarantee.
Have a look at How to Write a Action Listener for more information
Given the general complexity of what you are trying to do, +1 for a overall good attempt!
Related Topics
Including Jars in Classpath on Commandline (Javac or Apt)
How to Use Scanner to Accept Only Valid Int as Input
Can Java Finalize an Object When It Is Still in Scope
How to Get the Cellrow When There Is an Itemevent in the Jcombobox Within the Cell
Hibernate Throws Multiplebagfetchexception - Cannot Simultaneously Fetch Multiple Bags
Java Https Client Certificate Authentication
How Many Threads Can a Java Vm Support
Servlet For Serving Static Content
Number of Lines in a File in Java
Unicode Equivalents For \W and \B in Java Regular Expressions
Why Aren't Java Collections Remove Methods Generic
Why Should the Interface For a Java Class Be Preferred
What Is the Ellipsis (...) For in This Method Signature
Catching Java.Lang.Outofmemoryerror
Best Way to Parsedouble With Comma as Decimal Separator
Java: Prefix/Postfix of Increment/Decrement Operators
Why Filter() After Flatmap() Is "Not Completely" Lazy in Java Streams