I want to check if server application is available. After server is started I want to stop checking until the server changes status. How to do that with my code:
private static final String SERVER_ADDRESS = "192.144.10.10";
private static final int TCP_SERVER_PORT = 8890;
private static boolean connected = false;
static Socket s;
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(task, 01, 5001); }
static TimerTask task = new TimerTask() {
#Override
public void run() {
// TODO Auto-generated method stub
if (connected == false)
{
System.out.println(hostAvailabilityCheck());
}
}
};
public static boolean hostAvailabilityCheck()
{
boolean available = true;
try {
if (connected == false)
{ (s = new Socket(SERVER_ADDRESS, TCP_SERVER_PORT)).close();
}
}
catch (UnknownHostException e)
{ // unknown host
available = false;
s = null;
}
catch (IOException e) { // io exception, service probably not running
available = false;
s = null;
}
catch (NullPointerException e) {
available = false;
s=null;
}
return available;
}
Is there any better way to solve this?
The check method can be rewritten as follows (Java 7 and later):
public static boolean hostAvailabilityCheck() {
try (Socket s = new Socket(SERVER_ADDRESS, TCP_SERVER_PORT)) {
return true;
} catch (IOException ex) {
/* ignore */
}
return false;
}
In addition to simplifying the exception handling, this eliminates a pesky Socket leak. (If you are concerned with the time taken to do this check, then set a connection timeout before attempting to connect: see Setting a timeout for socket operations)
But the problems with this approach are many-fold:
It only tests that something is listening for connections. If your service is behind a proxy ... or is managed by something like the inetd service ... then the accepted connections don't mean your service is actually working.
This is going to cause your service to "see" connections that close down without sending a request. So you'd better code your service to deal with this "gracefully".
Doing this repeatedly adds to network and server load.
If you set a short timeout because you don't want the test to "freeze", then you risk setting it too short and judging the host to be down when it isn't.
After server is started I want to stop checking until the server changes status
That is next to impossible. The reason is that you won't be able to tell whether the server has "changed status" without checking. Or at least, you won't be able to do this without implementing an elaborate status notification service where the server calls the client to tell it is changing status. (And if "change status" includes "die" or "lost network connection", then you won't be able to make that notification reliable ... if at all.)
public static boolean hostAvailabilityCheck() {
try (Socket s = new Socket(SERVER_ADDRESS, TCP_SERVER_PORT)) {
return true;
} catch (IOException ex) {
/* ignore */
}
return false;
}
working, but the problem is that when you turn on the phone throught WI-FI it comes to a "screeching halt" and no action. for thought...=)
next code will be to work through WI-FI ... if you increase the connection time -
public static boolean isOnline() {
boolean b = true;
try{
InetSocketAddress sa = new InetSocketAddress("SERVER_IP_ADDRESS", PORT);
Socket ss = new Socket();
ss.connect(sa, 1); --> change from 1 to 500 (for example)
ss.close();
}catch(Exception e) {
b = false;
}
return b;
}
First check if server is running and the server accepts the connection.
public static boolean hostAvailabilityCheck()
{
s = new Socket(SERVER_ADDRESS, TCP_SERVER_PORT);
boolean available = true;
try {
if (s.isConnected())
{ s.close();
}
}
catch (UnknownHostException e)
{ // unknown host
available = false;
s = null;
}
catch (IOException e) { // io exception, service probably not running
available = false;
s = null;
}
catch (NullPointerException e) {
available = false;
s=null;
}
return available;
}
I used this method for my ServerUtil.
public static boolean isOnline() {
boolean b = true;
try{
InetSocketAddress sa = new InetSocketAddress("SERVER_IP_ADDRESS", PORT);
Socket ss = new Socket();
ss.connect(sa, 1);
ss.close();
}catch(Exception e) {
b = false;
}
return b;
}
Related
I am trying to find a bug is some RabbitMQ client code that was developed six or seven years ago. The code was modified to allow for delayed messages. It seems that connections are created to the RabbitMQ server and then never destroyed. Each exists in a separate thread so I end up with 1000's of threads. I am sure the problem is very obvious / simple - but I am having trouble seeing it. I have been looking at the exchangeDeclare method (the commented out version is from the original code which seemed to work), but I have been unable to find the default values for autoDelete and durable which are being set in the modified code. The method below in within a Spring service class. Any help, advice, guidance and pointing out huge obvious errors appreciated!
private void send(String routingKey, String message) throws Exception {
String exchange = applicationConfiguration.getAMQPExchange();
Map<String, Object> args = new HashMap<String, Object>();
args.put("x-delayed-type", "fanout");
Map<String, Object> headers = new HashMap<String, Object>();
headers.put("x-delay", 10000); //delay in miliseconds i.e 10secs
AMQP.BasicProperties.Builder props = new AMQP.BasicProperties.Builder().headers(headers);
Connection connection = null;
Channel channel = null;
try {
connection = myConnection.getConnection();
}
catch(Exception e) {
log.error("AMQP send method Exception. Unable to get connection.");
e.printStackTrace();
return;
}
try {
if (connection != null) {
log.debug(" [CORE: AMQP] Sending message with key {} : {}",routingKey, message);
channel = connection.createChannel();
// channel.exchangeDeclare(exchange, exchangeType);
channel.exchangeDeclare(exchange, "x-delayed-message", true, false, args);
// channel.basicPublish(exchange, routingKey, null, message.getBytes());
channel.basicPublish(exchange, routingKey, props.build(), message.getBytes());
}
else {
log.error("Total AMQP melt down. This should never happen!");
}
}
catch(Exception e) {
log.error("AMQP send method Exception. Unable to get send.");
e.printStackTrace();
}
finally {
channel.close();
}
}
This is the connection class
#Service
public class PersistentConnection {
private static final Logger log = LoggerFactory.getLogger(PersistentConnection.class);
private static Connection myConnection = null;
private Boolean blocked = false;
#Autowired ApplicationConfiguration applicationConfiguration;
#PreDestroy
private void destroy() {
try {
myConnection.close();
} catch (IOException e) {
log.error("Unable to close AMQP Connection.");
e.printStackTrace();
}
}
public Connection getConnection( ) {
if (myConnection == null) {
start();
}
return myConnection;
}
private void start() {
log.debug("Building AMQP Connection");
ConnectionFactory factory = new ConnectionFactory();
String ipAddress = applicationConfiguration.getAMQPHost();
String user = applicationConfiguration.getAMQPUser();
String password = applicationConfiguration.getAMQPPassword();
String virtualHost = applicationConfiguration.getAMQPVirtualHost();
String port = applicationConfiguration.getAMQPPort();
try {
factory.setUsername(user);
factory.setPassword(password);
factory.setVirtualHost(virtualHost);
factory.setPort(Integer.parseInt(port));
factory.setHost(ipAddress);
myConnection = factory.newConnection();
}
catch (Exception e) {
log.error("Unable to initialise AMQP Connection.");
e.printStackTrace();
}
myConnection.addBlockedListener(new BlockedListener() {
public void handleBlocked(String reason) throws IOException {
// Connection is now blocked
log.warn("Message Server has blocked. It may be resource limitted.");
blocked = true;
}
public void handleUnblocked() throws IOException {
// Connection is now unblocked
log.warn("Message server is unblocked.");
blocked = false;
}
});
}
public Boolean isBlocked() {
return blocked;
}
}
I have the following tcp server:
public class Server {
private Connection db;
private Statement statement;
private ServerSocket socket;
public static void main(String[] args) {
Server server = new Server();
server.initializeServer();
System.out.println("Server initialized");
server.listenConnections();
}
private void initializeServer() {
try {
db = DriverManager.getConnection("jdbc:mysql://localhost:3306/courseworkschema" +
"?verifyServerCertificate=false" +
"&useSSL=false" +
"&requireSSL=false" +
"&useLegacyDatetimeCode=false" +
"&" +
"&serverTimezone=UTC",
"Sergei",
"12345");
statement = db.createStatement();
socket = new ServerSocket(1024);
} catch (SQLException | IOException e) {
e.printStackTrace();
}
}
private void listenConnections() {
System.out.println("Listening connections ... ");
while (true) {
try {
Socket client = socket.accept();
new Thread(() -> {
System.out.println("Client accepted");
try {
OutputStream outputStream = client.getOutputStream();
InputStream inputStream = client.getInputStream();
String clientAction;
String queryContent;
boolean flag = true;
while (flag) {
byte[] msg = new byte[100];
int k = inputStream.read(msg);
clientAction = new String(msg, 0, k);
clientAction = clientAction.trim();
msg = new byte[100];
k = inputStream.read(msg);
queryContent = new String(msg, 0, k);
queryContent = queryContent.trim();
System.out.println(clientAction);
System.out.println(queryContent);
if (clientAction.equalsIgnoreCase("END")) {
flag = false;
}
else if (clientAction.equalsIgnoreCase("LOGIN")) {
System.out.println("Login action");
}
}
} catch (IOException e) {
e.printStackTrace();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
This server is created to communicate with database. Here's the way how I try to connect to this serverL
public class LoginController {
private LoginWindow window;
private Socket socket;
private InputStream is;
private OutputStream os;
public LoginController() {
connectToServer();
}
public void logInUser(String login, String password) {
if (!login.isEmpty() && !password.isEmpty()) {
sendDataToServer("LOGIN");
sendDataToServer("");
} else {
window.showMessageDialog("Fill the fields!", JOptionPane.ERROR_MESSAGE);
}
}
public void attachView(LoginWindow window) {
this.window = window;
}
private void connectToServer() {
try {
socket = new Socket("127.0.0.1", 1024);
System.out.println("Connected");
} catch (IOException e) {
e.printStackTrace();
}
}
private void sendDataToServer(String res) {
try {
os = socket.getOutputStream();
os.write(res.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}
When I run the server and then client, I have such logs in server:
Server initialized
Listening connections ...
Process finished with exit code -1
So, I can't understand why server doesn't wait and accept a connection from client, but closes after initializing and listening. So, what's the matter? I will appreciate any help. Thanks in advance!
UPD
When I run my app it started to work but I found out that code in Thread block isn't executed. I even can't understand, why does it happen
In your private void listenConnections() you are creating a Thread object but you are not telling it to start after its created thus it wont execute.
Your thread creation line should look something like this:
new Thread(() -> {
//your code
}).start();
From the javadocs:
https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#start()
public void start()
Causes this thread to begin execution; the Java Virtual Machine calls
the run method of this thread. The result is that two threads are
running concurrently: the current thread (which returns from the call
to the start method) and the other thread (which executes its run
method).
It is never legal to start a thread more than once. In particular, a
thread may not be restarted once it has completed execution.
Throws: IllegalThreadStateException - if the thread was already
started.
See Also: run(), stop()
Edited my question for clarification and code:
My goal is to pass my String data from my background thread, to my main application thread. Any help is appreciated.
Here is the code that creates the main background thread. This is located in my Server.java class
public class Server {
boolean isConnected = false;
Controller controller = new Controller();
public void startHost() {
Thread host = new Thread(() -> {
Controller controller = new Controller();
ServerSocket server = null;
try {
server = new ServerSocket(GeneralConstants.applicationPort);
} catch (BindException e2) {
System.out.println("Port Already in Use!");
} catch (IOException e) {
//do nothing
}
while (true) {
if (server == null) { break; }
try {
Socket client = server.accept();
System.out.println("Client Connected: " + isConnected);
if (!isConnected) {
controller.createClientHandler(client);
isConnected = true;
System.out.println("Client Connected: " + isConnected);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
host.setDaemon(true);
host.start();
}
Here is the code that is then called when a client is connected, located in my Controller.java class.
public synchronized void createClientHandler(Socket client) {
boolean alreadyConnected = false;
if (alreadyConnected) {
//do NOT assign multiple threads for each client
} else {
ClientHandler handleClients = new ClientHandler("client", client);
}
}
The program then creates two background threads for my client, one to manage receiving messages, and sending messages.
public ClientHandler(String name, Socket s) {
clientSocket = s;
clientName = name;
receiveThread = new Thread(this::receive);
sendThread = new Thread(this::send);
connected = clientSocket.isConnected();
receiveThread.start();
sendThread.start();
}
The thread then successfully creates the inputstream and passes the object to my controller. Which then process and grabs a string assigning it to a variable
public synchronized void handleReceivedPacket(String name, BufferedReader in) {
try {
data = in.readLine();
System.out.println("Successfully assigned data to: " + data);
} catch (IOException e) {
System.out.println("Unable to read result data");
}
}
How do I access my String data from the main thread without getting null?
Aka I can call (or something similar)
controller.returnData();
from my main application. From which it'll either return null (no data yet), or actually return my data. Right now, it's always null.
Edit, this is what's actually calling controller.returnData() {
I don't want to paste a massive amount of code for fear of reaching StackOverflow's code limit, so here's my application structure.
My JavaFX creates the scene, and creates a root gridpane, it then calls a method that creates sub gridpanes based the specified input. Aka, a user can press "Main Menu" that calls my method setScene() which removes the current "sub-root" gridpane and creates a "new" scene. Right now, I have a GameBoard.java class which on button press, calls controller.returnData()
PassOption.setOnAction(event -> {
System.out.println(controller.returnData());
});
There is no functional purpose for this besides testing. If I can receive the data, then I can expand on this using the data.
Start thinking about design. In network applications you typically have to manage the following responsibilites:
Connected clients and their state (connection state, heartbeats, ...)
Received messages from the clients
Messages to transmit to the clients
It makes sense to separate those responsibilities in order to keep the code clean, readable and maintainable.
Separation can mean both, thread-wise and class-wise.
For example, you could implement it as follows:
The class ClientAcceptor is responsible for opening the socket and accepting clients. As soon as a client has connected, it delegates the further work to a controller and then waits for other clients:
public class ClientAcceptor implements Runnable {
#Override
public void run() {
while (true) {
ServerSocket server;
try {
server = new ServerSocket(1992);
Socket client = server.accept();
if (client.isConnected()) {
controller.createClientHandler(client);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
The controller could then create a handler (if the controller decides to do so, e.g. it could also decline the client). The ClientHandler class could look as follows:
public class ClientHandler {
private Thread receiveThread;
private Thread sendThread;
private boolean connected;
private Socket clientSocket;
private String clientName;
private LinkedBlockingDeque<byte[]> sendQueue;
public ClientHandler(String name, Socket s) {
clientSocket = s;
clientName = name;
receiveThread = new Thread(() -> receive());
sendThread = new Thread(() -> send());
connected = clientSocket.isConnected();
receiveThread.start();
sendThread.start();
}
private void receive() {
BufferedInputStream in = null;
try {
in = new BufferedInputStream(clientSocket.getInputStream());
} catch (IOException e) {
connected = false;
}
while (connected) {
try {
byte[] bytes = in.readAllBytes();
if (bytes != null && bytes.length > 0) {
controller.handleReceivedPacket(clientName, bytes);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void send() {
BufferedOutputStream out = null;
try {
out = new BufferedOutputStream(clientSocket.getOutputStream());
} catch (IOException e) {
connected = false;
}
while (connected) {
byte[] toSend = sendQueue.getFirst();
if (toSend != null && toSend.length > 0) {
try {
out.write(toSend);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public void send(byte[] packet) {
sendQueue.add(packet);
}
public void close() {
connected = false;
}
}
The ClientHandler is responsible for receiving and transmitting data. If a packet arrives it informes the controller, which parses the packet. The ClientHandler also provides a public API to send data (which is stored in a queue and handled by a thread) and close the connection.
The above code examples are neither tested, nor complete. Take it as a starting point.
I am writing a code to send a UDP Multicast over Wifi from my mobile device. There is a server code running on other devices in the network. The servers will listen to the multicast and respond with their IP Address and Type of the system (Type: Computer, Mobile Device, Raspberry Pi, Flyports etc..)
On the mobile device which has sent the UDP Multicast, I need to get the list of the devices responding to the UDP Multicast.
For this I have created a class which will work as the structure of the device details.
DeviceDetails.class
public class DeviceDetails
{
String DeviceType;
String IPAddr;
public DeviceDetails(String type, String IP)
{
this.DeviceType=type;
this.IPAddr=IP;
}
}
I am sending the UDP Multicast packet at the group address of 225.4.5.6 and Port Number 5432.
I have made a class which will call a thread which will send the UDP Packets. And on the other hand I have made a receiver thread which implements Callable Interface to return the list of the devices responding.
Here is the code:
MulticastReceiver.java
public class MulticastReceiver implements Callable<DeviceDetails>
{
DatagramSocket socket = null;
DatagramPacket inPacket = null;
boolean check = true;
public MulticastReceiver()
{
try
{
socket = new DatagramSocket(5500);
}
catch(Exception ioe)
{
System.out.println(ioe);
}
}
#Override
public DeviceDetails call() throws Exception
{
// TODO Auto-generated method stub
try
{
byte[] inBuf = new byte[WifiConstants.DGRAM_LEN];
//System.out.println("Listening");
inPacket = new DatagramPacket(inBuf, inBuf.length);
if(check)
{
socket.receive(inPacket);
}
String msg = new String(inBuf, 0, inPacket.getLength());
Log.v("Received: ","From :" + inPacket.getAddress() + " Msg : " + msg);
DeviceDetails device = getDeviceFromString(msg);
Thread.sleep(100);
return device;
}
catch(Exception e)
{
Log.v("Receiving Error: ",e.toString());
return null;
}
}
public DeviceDetails getDeviceFromString(String str)
{
String type;
String IP;
type=str.substring(0,str.indexOf('`'));
str = str.substring(str.indexOf('`')+1);
IP=str;
DeviceDetails device = new DeviceDetails(type,IP);
return device;
}
}
The following code is of the activity which calls the Receiver Thread:
public class DeviceManagerWindow extends Activity
{
public void searchDevice(View view)
{
sendMulticast = new Thread(new MultiCastThread());
sendMulticast.start();
ExecutorService executorService = Executors.newFixedThreadPool(1);
List<Future<DeviceDetails>> deviceList = new ArrayList<Future<DeviceDetails>>();
Callable<DeviceDetails> device = new MulticastReceiver();
Future<DeviceDetails> submit = executorService.submit(device);
deviceList.add(submit);
DeviceDetails[] devices = new DeviceDetails[deviceList.size()];
int i=0;
for(Future<DeviceDetails> future :deviceList)
{
try
{
devices[i] = future.get();
}
catch(Exception e)
{
Log.v("future Exception: ",e.toString());
}
}
}
}
Now the standard way of receiving the packet says to call the receive method under an infinite loop. But I want to receive the incoming connections only for first 30seconds and then stop looking for connections.
This is similar to that of a bluetooth searching. It stops after 1 minute of search.
Now the problem lies is, I could use a counter but the problem is thread.stop is now depricated. And not just this, if I put the receive method under infinite loop it will never return the value.
What should I do.? I want to search for say 30 seconds and then stop the search and want to return the list of the devices responding.
Instead of calling stop(), you should call interrupt(). This causes a InterruptedException to be thrown at interruptable spots at your code, e.g. when calling Thread.sleep() or when blocked by an I/O operation. Unfortunately, DatagramSocket does not implement InterruptibleChannel, so the call to receive cannot be interrupted.
So you either use DatagramChannel instead of the DatagramSocket, such that receive() will throw a ClosedByInterruptException if Thread.interrupt() is called. Or you need to set a timeout by calling DatagramSocket.setSoTimeout() causing receive() to throw a SocketTimeoutException after the specified interval - in that case, you won't need to interrupt the thread.
Simple approach
The easiest way would be to simply set a socket timeout:
public MulticastReceiver() {
try {
socket = new DatagramSocket(5500);
socket.setSoTimeout(30 * 1000);
} catch (Exception ioe) {
throw new RuntimeException(ioe);
}
}
This will cause socket.receive(inPacket); to throw a SocketTimeoutException after 30 seconds. As you already catch Exception, that's all you need to do.
Making MulticastReceiver interruptible
This is a more radical refactoring.
public class MulticastReceiver implements Callable<DeviceDetails> {
private DatagramChannel channel;
public MulticastReceiver() {
try {
channel = DatagramChannel.open();
channel.socket().bind(new InetSocketAddress(5500));
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
public DeviceDetails call() throws Exception {
ByteBuffer inBuf = ByteBuffer.allocate(WifiConstants.DGRAM_LEN);
SocketAddress socketAddress = channel.receive(inBuf);
String msg = new String(inBuf.array(), 0, inBuf.capacity());
Log.v("Received: ","From :" + socketAddress + " Msg : " + msg);
return getDeviceFromString(msg);;
}
}
The DeviceManagerWindow looks a bit different; I'm not sure what you intend to do there, as you juggle around with lists and arrays, but you only have one future... So I assume you want to listen for 30 secs and fetch as many devices as possible.
ExecutorService executorService = Executors.newFixedThreadPool(1);
MulticastReceiver receiver = new MulticastReceiver();
List<DeviceDetails> devices = new ArrayList<DeviceDetails>();
long runUntil = System.currentTimeMillis() + 30 * 1000;
while (System.currentTimeMillis() < runUntil) {
Future<Object> future = executorService.submit(receiver);
try {
// wait no longer than the original 30s for a result
long timeout = runUntil - System.currentTimeMillis();
devices.add(future.get(timeout, TimeUnit.MILLISECONDS));
} catch (Exception e) {
Log.v("future Exception: ",e.toString());
}
}
// shutdown the executor service, interrupting the executed tasks
executorService.shutdownNow();
That's about it. No matter which solution you choose, don't forget to close the socket/channel.
I have solved it.. you can run your code in following fashion:
DeviceManagerWindow.java
public class DeviceManagerWindow extends Activity
{
public static Context con;
public static int rowCounter=0;
Thread sendMulticast;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_device_manager_window);
WifiManager wifi = (WifiManager)getSystemService( Context.WIFI_SERVICE );
if(wifi != null)
{
WifiManager.MulticastLock lock = wifi.createMulticastLock("WifiDevices");
lock.acquire();
}
TableLayout tb = (TableLayout) findViewById(R.id.DeviceList);
tb.removeAllViews();
con = getApplicationContext();
}
public void searchDevice(View view) throws IOException, InterruptedException
{
try
{
sendMulticast = new Thread(new MultiCastThread());
sendMulticast.start();
sendMulticast.join();
}
catch(Exception e)
{
Log.v("Exception in Sending:",e.toString());
}
here is the time bound search.... and you can quit your thread using thread.join
//Device Will only search for 1 minute
for(long stop=System.nanoTime()+TimeUnit.SECONDS.toNanos(1); stop>System.nanoTime();)
{
Thread recv = new Thread(new MulticastReceiver());
recv.start();
recv.join();
}
}
public static synchronized void addDevice(DeviceDetails device) throws InterruptedException
{
....
Prepare your desired list here.
....
}
}
Dont add any loop on the listening side. simply use socket.receive
MulticastReceiver.java
public class MulticastReceiver implements Runnable
{
DatagramSocket socket = null;
DatagramPacket inPacket = null;
public MulticastReceiver()
{
try
{
socket = new DatagramSocket(WifiConstants.PORT_NO_RECV);
}
catch(Exception ioe)
{
System.out.println(ioe);
}
}
#Override
public void run()
{
byte[] inBuf = new byte[WifiConstants.DGRAM_LEN];
//System.out.println("Listening");
inPacket = new DatagramPacket(inBuf, inBuf.length);
try
{
socket.setSoTimeout(3000)
socket.receive(inPacket);
String msg = new String(inBuf, 0, inPacket.getLength());
Log.v("Received: ","From :" + inPacket.getAddress() + " Msg : " + msg);
DeviceDetails device = getDeviceFromString(msg);
DeviceManagerWindow.addDevice(device);
socket.setSoTimeout(3000)will set the listening time for the socket only for 3 seconds. If the packet dont arrive it will go further.DeviceManagerWindow.addDevice(device);this line will call the addDevice method in the calling class. where you can prepare your list
}
catch(Exception e)
{
Log.v("Receiving Error: ",e.toString());
}
finally
{
socket.close();
}
}
public DeviceDetails getDeviceFromString(String str)
{
String type;
String IP;
type=str.substring(0,str.indexOf('`'));
str = str.substring(str.indexOf('`')+1);
IP=str;
DeviceDetails device = new DeviceDetails(type,IP);
return device;
}
}
Hope that works.. Well it will work.
All the best. Let me know if any problem.
I am using a ServerSocket port to run one instance only of my Java Swing application, so if a user tries to open another instance of the program, i show him a warning that "Another instance is already open". This works fine, but instead of showing this message i want to set focus on the running application itself, like some programs does (MSN Messenger), even if it was minimized.
Is there a solution for this for various operating systems ?
Since you use a server socket I assume that you use the java.net.BindException to detect that you application is already running. If you start a second instance you could send a control message which instructs you first app to normalize (if minimized) before exiting.
if (msg == BRING_TO_FRONT ) {
frame.setState(Frame.NORMAL);
frame.toFront();
}
I don't know if this is absolutely right, but here's the final code i've used and it works fine for me :
public class Loader {
private static final int PORT = 9999;
private static ServerSocket serverSocket = null; // Server
private static Socket socket = null; // CLient
private static final String focusProgram = "FOCUS";
public static void main(String[] args) {
if( !isProgramRunning() ) {
Main main = new Main();
main.setVisible( true );
}
else {
System.exit( 2 );
}
}
private static boolean isProgramRunning() {
try {
serverSocket = new ServerSocket(PORT,0,InetAddress.getByAddress(new byte[] {127,0,0,1})); // Bind to localhost adapter with a zero connection queue.
SwingWorker<String, Void> anotherThread = new SwingWorker<String, Void>() { // Do some code in another normal thread.
#Override
public String doInBackground() { // This method is to execute a long code in the other thread in background.
serverSocketListener();
return "";
}
};
anotherThread.execute(); // Execute the other tread.
}
catch (BindException e) {
System.err.println("Already running.");
clientSocketListener();
return true;
}
catch (IOException e) {
System.err.println("Unexpected error.");
e.printStackTrace();
return true;
}
return false;
}
public static void serverSocketListener() { // Server socket
try {
System.out.println( "Listener socket opened to prevent any other program instance." );
socket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
if( in.readLine().equals( focusProgram ) ) { // Restore the opened instance however you want.
Global.getCurrentFrame().setState(Frame.NORMAL);
Global.getCurrentFrame().toFront();
}
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
}
public static void clientSocketListener() { // Client socket
try{
socket = new Socket(InetAddress.getByAddress( new byte[] {127,0,0,1}), PORT );
PrintWriter out = new PrintWriter( socket.getOutputStream(), true );
out.println( focusProgram );
} catch (IOException e) {
System.out.println("No I/O");
System.exit(1);
}
}
}