UI Freeze in simple Socket (Java) app using SWT for UI - java

I'm new to Java Socket Programming and currently exploring its Socket APIs. I've created a new simple App that starts ServerSocket and listens for Clients, when client writes something on the socket, server allocates new thread for that client. I tried first using console app and everything worked fine. Now, I've made GUI for the same using SWT (WindowBuilder plugin in Eclipse 3.7). The Window has a button which toggles listening of the server On and Off. Below is the code written in SWT Button's click event which will start listening for clients.
if(!isServerRunning)
{
btnServerRunner.setText("Stop Server");
isServerRunning = true;
while (listening)
{
try
{
new ClientHandler(listener.accept()).start();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
else
{
try
{
listener.close();
}
catch(Exception ex)
{
ex.printStackTrace();
}
btnServerRunner.setText("Start Server");
isServerRunning = false;
}
The ClientHandler class has Thread extended and hence will launch new thread for every new client. I know above code works for console app but will not work for GUI since I'm throwing app into infinite loop of listening for client sockets in button's click. What is the elegant way to start and stop ServerSocket for listening for clients that doesn't freeze the app UI?
Thanks.

You should use a separate thread for accepting client connections. The button could just start and interrupt that thread.

You need to run your Server in a separate thread (from the UI dispatch thread).

Related

Keep singleton instance of java application

I have a jar file that displays a JFrame when it is executed.
I don't want to allow duplicate execution of my Jar file.
Every time before creating the frame, using Java I want check whether the Jar is already executing. If my app. already has an instance on-screen, I want to bring it to front.
How can I do that?
Please suggest me a way.
There is no regular method in java for single instance of an application.
However you can use Socket programming technique to achieve your goal.
When the instance is creating it attempts to listen a ServerSocket. If it could open the ServerSocket it means there are no another instance of the application. So, it keeps the ServerSocket live until the program is shutdown. If it could not open the ServerSocket, it means the application already have another instance. So you can exit application silently. Additionally you don't need to reset your settings when shutdown the application.
Try following example
public class SingletonApplication extends JFrame implements Runnable {
//count of tried instances
private int triedInstances = 0;
//the port number using
private static final int PORT = 5555;
public static void main(String[] args) {
SingletonApplication application = new SingletonApplication();
application.setTitle("My Singleton Application");
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.setSize(500, 500);
application.setVisible(true);
}
public SingletonApplication() {
super();
//run socket listening inside a thread
Thread thread = new Thread(this);
thread.start();
}
#Override
public void run() {
try {
//create server socket
ServerSocket serverSocket = new ServerSocket(PORT);
//listing the socket to check new instances
while (true) {
try {
//another instance accessed the socket
serverSocket.accept();
//bring this to front
toFront();
//change the title (addtional);
triedInstances++;
setTitle("Tried another instances : " + triedInstances);
} catch (IOException ex) {
//cannot accept socket
}
}
} catch (IOException ex) {
//fail if there is an instance already exists
try {
//connect to the main instance server socket
new Socket(InetAddress.getLocalHost(), PORT);
} catch (IOException ex1) {
//do nothing
} finally {
//exit the system leavng the first instance
System.exit(0);
}
}
}
}
EDIT:
Additionally: It can pass your runtime arguments into the main instance of the application via the client Socket. So, it's possible to make the main instance to perform required task such opening file or playing music by adding some additional code to read the InputStream of accepted Socket when calling accept() method.
I had the same situation.
What I did is I used to open a file in write mode and delete the file when I close the application.
By doing this I have a known proof that my program is running.
Each time I open the application I check for the existence of that file and if I find my file, it is running then I used to alert him
"An instance is already running".
Even if one tries to delete that file it says that it is open in another application.
I used a socket too, via RMI.
The application is an RMI host/server, accepts a Remote Method Invokation on a port.
In the main, at startup on tries as RMI client to get an RMI server on that port.
Is it there one does a remote call passing the command line args (to open another document for instance). And then quits.
As a server on being called that remote method one brings the application to front using toFront() of the window.
JUnique accomplishes the first part--blocking multiple instances of the same program. Getting the existing instance to come to the front is another task that I'm not sure how to approach.

Java TCP server socket accepting multiple clients on different ports

I am trying to build a socket that is capable of having multiple TCP connections, at different ports with multiple clients simultaneously.
The situation is my socket has to receive commands from a server and redirect the commands to wireless sensors (one command to one sensor, not broadcasting), and be able to collect the corresponding data from the sensors and then send them back to the server. Connections with the server would be using TCP, but connections with the sensors could be TCP or UDP.
My main concern are the TCP connections. I am looking into java multithreaded or thread pooled socket tutorials. But the examples I’ve seen were only using a single port to handle all the connections. I’m also trying to look into other possible solutions: utilizing tomcat server, java servlet/JSP, socket channel etc…
I’m not an expert in networking or socket programming so I really hope someone with experience could point me in the right direction. Thank you for any help you can provide in this situation.
Not sure if I fully understand but it seems like it is unnecessary for me to obtain multiple ports for my situation. Seems like I would need to focus on multi threaded sockets and Java NIO topics?
And again thank you for the advice and help.
This is rather a big project to be answered in full here. But here are some general guides:
1) If you want to create a socket on one port you need to create one thread to run it. That is called a server socket. Therefore, from the main thread u need to call one thread for every socket on every port.
2) Each server socket keeps listening on a certain port and waits for clients to connect.
when a client actually connects, the server socket should open another thread for that connection alone and return back to listening.
while(myServerSocket.accept())
{
Open connection thread
}
My advice would be to learn online about how to open threads from classes and then follow the guide above.
Unless you are going over 10k connections then most web servers would be able to handle the traffic.
But maybe you should get more details on the difference between a connection, a socket, and a port. Take a look at this: What is the difference between a port and a socket?
On your question: one port can handle many connections. You don't need different ports for different connections.
My understanding of this request is that you would need to deploy several instances of your server socket application listening on their respective ports and capable of servicing multiple client connections.
By way of mathematical induction, if you have written your server app properly it should work anywhere it is deployed. Below is sample of what your server socket application run should look like
public void run()
{
try
{
while(true)
{
try
{
Thread client_thread= new Thread(new ClientReqProcessor(serverSocket.accept()));
client_thread.start();
}
catch(Exception ex)
{
logger.error("connection error: "+ex.getMessage());
}
}
}
}
Why do you want to use multiple ports? You can have multiple connections on one listening port. The connection itself runs always on different ports.
while (running)
{
try
{
#SuppressWarnings("resource")
Socket socket = serverSocket.accept();
new ServerHandler(socket); // ServerHandler is your class to handle one connection.
}
catch (IOException e)
{
...
}
}
When you really need different ports, you can create a lot of Threads, each with a ServerSocket. Ports are one of the most limited resources on your computer. The running Threads are much cheaper.
for(int i = 1000; i < 1100; i++)
{
final int port = i;
new Thread(new Runnable()
{
#Override
public void run()
{
try
{
ServerSocket serverSocket = new ServerSocket(port);
Socket socket = serverSocket.accept();
new ServerHandler(socket); // ServerHandler is your class to handle one connection.
}
catch(IOException e)
{
...
}
}
}).start();
}

shutdown TCP thread server

I coded a little TCP thread Server, which creates a new thread for every server.accept(). Nearly everything works great, but I have problems to kill all threads per interrupt. (I use a ServiceExecutor to manage the threads. Therefore I use the shutdownNow method to reach the interrupt-methods) The Worker-instances use a BufferedReader and it's readline-method to receive and compute the input. AFAIK the readline blocks and would not react on an interrupt, but how to stop it?
while(!isInterrupted()){
try {
clientSocket = this.serverSocket.accept();
} catch(IOException e){
break;
}
this.threadPool.execute(new ThreadWorker(clientSocket));
}
threadPool.shutdownNow();
try{
serverSocket.close();
}catch(IOException e){
//todo
}
I tried to close the ServerSocket to kill the Input/Output Streams, but it didn't work as expected.
A couple alternatives:
1) If you are closing the whole app, and there is nothing of importance to explicitly close, call System.Exit(0). HEALTH WARNING - doing this causes some developers to have apoplectic fits and post endlessly about 'cleaning up gracefully'.
2) Keep a thread-safe list of all client sockets in the accept() thread. Pass a reference to this list as part of your client context that is passed to the client<>server threads. Add new connections to the list in the accept() thread. When a client thread detects a disconnect, remove its entry from the list. When you want to close all clients, iterate the list and close the client sockets - this will cause the readline method to return early, with an error, in the client threads.

Append to JTextArea

I am making server side app, but when I am trying to append text to the JTextarea, it's not working. It prints, however, to the console.
It worked fine until I added the line serverSocket.accept().
Here is my code:
try {
serverSocket=new ServerSocket(4545);
LogOutput.append("Seccessfuly connected\n" );
System.out.println("Seccessfuly connected\n" );
StartButon.setEnabled(false);
while(true){
LogOutput.append("waiting for client\n" );
System.out.println("waiting for client\n" );
serverSocket.accept();
LogOutput.append("Client connected to server\n" );
}
}
catch(Exception e){
LogOutput.append("cannot establish connection : "+ e +"\n" );
StartButon.setEnabled(true);
}
You're completely blocking the Swing event thread or EDT. Get most of that code, starting with the while (true) block onto a background thread if you want your Swing GUI to function in conjunction with a long-running process. Please read the Concurrency in Swing tutorial to see why this matters, and how to solve this issue with a SwingWorker object.
From the given code snippet and your question it seems you are looking for
Client connected to server\n
to be added to your textArea.
serverSocket.accept();
LogOutput.append("Client connected to server\n" );
Once you say serverSocket.accept() now it will wait for client connection to arrive, unless there is some client your next line of code is not going to be executed. serverSocket.accept is blocking method, Start your client program and your server will start processing next line of code.
From the docs
public Socket accept() throws IOException
Listens for a connection to be made to this socket and accepts it. The method blocks until a connection is made.

SeverSocket stops accepting

I'm working on a game with a event based structure with the main game logic hosted on a server; currently it's a very small featureset that only allows to host one game between exactly two participants. I've read on various questions about ServerSocket and none of them answers my question. I already took a look at
ServerSocket accept continues to block
ServerSocket.accept()
Java ServerSocket won't accept new connections until close() is called on the accepted socket
ServerSocket accept() method
In my project I utilize ObjectInputStream and ObjectOutputStream. Everything works as expected (receiving / sending both on server and client side), but after both sockets are registered, the accept method of the ServerSocket instance continues to block forever, even if the same code is invoked before. Perhaps it's an issue that appears after communicating over a socket once?
My server log shows the following:
waiting for accept
accepting first socket
sending an event to socket1 for informing about waiting for the opponent
waiting for accept
accept second socket
sending responses to both sockets
waiting for accept (and blocking forever)
When the log says response events where sent, they were properly received and processed at the client side. The client side debug outputs show that the next event is definitely sent. Maybe it's about not closing the client sockets (mentioned in the third linked question)? Anyway I can't close the client sockets because further communication would be impossible.
Client side code
public void send(Event e) {
try {
ObjectOutputStream out = new ObjectOutputStream(
socket.getOutputStream());
out.writeObject(e);
out.flush();
log.debug("sending event... "+e);
}
catch(IOException ioe) {
log.fatal("constructing oos failed", ioe);
}
}
Server side code
#Override
public void run() {
running = true;
while(running) {
try {
Socket s = socket.accept();
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
Event event = (Event) ois.readObject();
try {
Event[] response = controller.consume(event);
ObjectOutputStream oos = new ObjectOutputStream(sockets[0].getOutputStream());
oos.writeObject(response[0]);
oos.flush();
ObjectOutputStream oos2 = new ObjectOutputStream(sockets[1].getOutputStream());
oos2.writeObject(response[1]);
oos2.flush();
}
catch(...) {
// multiple catch clauses for different exceptions
// all just logging (nothing passes silently!)
}
}
}
For shortening, the method for assigning the two sockets to the Socket[] array was left out, but since there are no exceptions, keeping the socket works. Do you have any idea what could cause the described behavior? Thank you in advance.
The accept method only accepts new connections. Since you only have two clients attempting to connect to your server, it will hang indefinitely on your third invocation of accept.
Side note: You don't need to continuously create new ObjectInputStreams and ObjectOutputStreams. You can just create one of each for each Socket and keep references to them for reuse.

Categories