I have a class which connects to a server as below.
#Override
public void run() {
while (running) {
try {
msgHandler.log("Connecting to " + host + ":" + port);
Socket s = new Socket(host, port);
if (s.isConnected() && !s.isClosed()) {
msgHandler.connectionInit(s);
}
BufferedInputStream input = new BufferedInputStream(s.getInputStream());
}
}
The consumer which is the msgHandler, frequently polls the socket if a connection ever goes down as below.
#Override
public void connectionInit(Socket s) throws IOException {
logger.info("Connected to AWW Service on " + configuration.getAwwHost() + ":" + configuration.getAwwPort());
output = new BufferedOutputStream(s.getOutputStream());
connector.componentReady();
Timer t = new Timer();
t.schedule(new TimerTask() {
#Override
public void run() {
try {
pollServer();
} catch (IOException e) {
// SOCKET GETS BROKEN HERE
}
}
}, 0, 25000);
}
Question is, how can i communicate from the exception i get when the socket connection gets broken back to the run() thread, so it can try to reinitialize the socket and the input stream?
I dont think a notify() or wait() mechanism is appropriate here as wait() will just put the run() thread to sleep.
I was thinking whats the equivalent of setting a flag when the connection gets broken, and the run() thread constantly checks the flag, and when it is set to true, it reinitialize the socket. But i am sure there would be a more efficient multi threading approach native to java for achieving this.
I think the simplest approach is using an AtomicBoolean variable that is accessible to both threads - you could pass the variable in when constructing each thread's run class if necessary. Nice thing about AtomicBoolean is that it is already thread safe/synchronized and mutable so that it can be passed around and modified by reference.
See this similar question for some more details.
I think that in the run() function, you should have a code like the following one.
// ...
try
{
// ...
int read = input.read(...);
// ...
}
catch (IOException e)
{
// TODO: terminate the thread and restart a new connection
}
So, if an error occurs during the pollServer() call, also my code above should generate an exception.
Also when you call the close function of a Socket object, the input and output streams will generate the relative exceptions.
Related
In my android app, my activity is starting another thread for some socket network operations, and this thread is always waiting for incoming data from the socket(blocking on read() function in a while loop).
Now, when my activity gets destroyed, I would like to keep things clean, and destroy that thread. To implement this functionality, I defined a volatile boolean variable isSupposedToStop which would be initialized to false, and when onStop() gets called, it sets that boolean to true, and calls socket.shutdownInput() which causes the thread blocking on read() to throw an IOException, then read the isSupposedToStop boolean to know that it is supposed to stop.(if you have better ways feel free to discuss it).
So, in my run() implementation after connecting my socket I have:
sock= new Socket("127.0.0.1", 1234);
InputStream is= sock.getInputStream();
byte[] buffer= new byte[200];
while(true){
if(isSupposedToStop) return;
try {
is.read(msgSizeBuff, 0, 200);
} catch(IOException e){
}
if(isSupposedToStop) return;
//do something with the received message
}
in onStop(), I have:
isSupposedToStop= true;
if(sock!= null) {
try {
sock.shutdownInput();
sock.close();
} catch (IOException e) {
}
}
thread.join()
that is working good. as when the thread is waiting for new data (blocking on read()), read() throws an IOException immediately when onStop() calls shutdownInput(), and control is back to the thread which reads my boolean value and exits.
but the problem is happening if onStop() gets called when the thread is still waiting to establish the connection (blocking on new Socket()) so if the host is down for example the app freezes for about 3 seconds, so do you recommend to just omit the thread.join() call? or is there a way to wake up this thread?
Once you have called the read method you are essentially blocked - you can only escape by interrupting the thread.
public void test() {
Thread socketThread = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("Hello");
}
});
// Do your stuff.
//...
// Time to quit - should abort any blocked reads.
socketThread.interrupt();
}
Another alternative - this may not work at all - is to use the available method of InputStream.
public void test() throws IOException {
Socket sock = new Socket("127.0.0.1", 1234);
InputStream is = sock.getInputStream();
boolean done = false;
while (!done) {
int available;
if ((available = is.available()) > 0) {
// Your read stuff.
is.read(buffer, 0, available);
}
}
}
The new Socket isn't supposed to block networking. Not even a SYN/ACK.
Therefore you can setSOTimeout() right after construction. But you wouldn't set it to anything less than 3 seconds to be fair.
You are suggesting that it takes 3 seconds to respond to a socket.close()... So I fear it cannot get any faster, but you can try a thread.interrupt(), in case it is sitting in interruptable (non native) code.
I'm trying to use server sockets to set up a connection between a client and a server. I'm also not using java.nio.
The problem is that I'm constantly sending a test message, and detecting whether if it is successful in sending the message (the client is still connected), if not, then the client is disconnected.
Shown here:
try
{
Scanner in = new Scanner(socket.getInputStream());
BufferedReader in_2 = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(stopThread)
{
if(in_2.ready())
{
String message = in_2.readLine();
dt = new DateTime();
PrintStream out = new PrintStream(socket.getOutputStream());
server.detect(message, dataSets, out);
dataSets.add(message);
GUI.textArea_1.append(message + "\r\n");
GUI.textArea_1.setCaretPosition(GUI.textArea_1.getDocument().getLength());
}
else
{
PrintStream out = new PrintStream(socket.getOutputStream());
out.println("Testing Connection \r\n");
if(out.checkError())
{
try
{
socket.close();
}
catch (IOException e)
{
e.printStackTrace();
}
stopThread = false;
GUI.textArea.append(userName + " disconnected \r\n");
GUI.textArea.setCaretPosition(GUI.textArea.getDocument().getLength());
server.inputDataForm(userName, dt, dataSets);
}
Thread.sleep(3000);
}
}
The problem is that the Thread.sleep(3000) is actually interfering with getting data, since after 3 seconds, I will get a huge amount of data (because I stopped the thread for 3 seconds).
Now, what I proposed is a anonymous class in the else statement.
class runThread implements runnable
{
void run()
{
//Put the else statement here
}
}
But the stopThread = false is not a constant, which I'm trying to control.
Other threads I've searched only puts variables inside main inside the anonymous class, but I need stopThread to stop the while loop if the client is disconnected.
Does anyone have an idea?
Thanks!
Consider setting a short timeout on your socket. This will allow you to control how long your thread will block while waiting for data from the socket.
If data are not quickly available, a very specific java.net.SocketTimeoutException will be raised. You can handle this exception by checking your stopThread flag. If it is set, you can return from the method. Otherwise, the socket is still valid and you can try another read operation with timeout.
If any other exception type is thrown, your socket is probably no longer valid.
socket.setSoTimeout(20); /* 1/50th of a second. */
BufferedReader in = new BufferedReader
(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
while (!stop) {
try {
String message = in.readLine();
if (message == null)
handleEOF();
else
handleMessage(message);
} catch(SocketTimeoutException ignore) {
/* Loop back to check "stop" flag. */
continue;
} catch(IOException ex) {
handleDisconnection();
break;
}
}
By the way, if you are using Swing, remember that you can only modify graphical components from Swing's Event Dispatch Thread, and you can't tie up the EDT in long-running operations like this socket handling. You should be passing tasks from this thread to Swing's invokeLater() utility.
Why don't you make a class that implements runnable but also has the method stop();
public class MyRunner implements Runnable(){
MutableBoolean stop = false;
public void run(){...}
public void stop(){
stop = true;
}
}
I'm trying to create a server to send a message which is based on the calculation result from another class.
My question is that since the calculation result is from another class, how do I make the server pause till the result is ready, and how should I pass the result to my server class and send out the result?
public class MyServer {
ServerSocket providerSocket;
Socket connection = null;
static ObjectOutputStream out;
ObjectInputStream in;
String message;
public static String myServerSend;
BufferedReader data = new BufferedReader(data);
MyServer() {}
void run() {
try {
providerSocket = new ServerSocket(2013, 10);
System.out.println("Waiting for connection");
connection = providerSocket.accept();
out = new ObjectOutputStream(connection.getOutputStream());
out.flush();
in = new ObjectInputStream(connection.getInputStream());
do {
try {
message = (String) in.readObject();
System.out.println("server receive>" + message);
// HERE IS MY QUESTION
// myServerSend is the result from other class,
//How can I pause the server here till myServerSend is ready???????
sendMessage(myServerSend);
} catch (ClassNotFoundException classnot) {
System.err.println("Data received in unknown format");
}
} while (!message.equals("bye"));
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
//write msg into ObjectOutputStream
public static void sendMessage(String msg) {
try {
out.writeObject(msg);
out.flush();
System.out.println("server send>" + msg);
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
Use
Thread.sleep(30000); // Milli secs - 30 secs -- Put your sleep time
sendMessage(myServerSend);
Without more specific info about what you have tried and why you have discarded what you have tried, I see several options here.
Call directly the other class and wait till the result is ready. This may not be a good idea if the calculation takes too long, but if not, it's the simplest way.
You can apply polling and get the server to sleep for a certain amount of time to not exhaust resources while waiting for an answer.
Use synchronized objects and concurrency via wait and notify methods. Some useful links on this: 1 2 3
You have few options to acheive this:
1- Create a Thread for your calculation and call join to make your server wait for the thread to finish
Thread thread = new Thread() {
public void run(){
// Call your calculation class
}
}
thread.start();
thread.join(); // surround with try and catch
// or you can use to timeout if the calculation took long
// thread.join(MAX_TIME_MILLIS);
sendMessage(myServerSend);
2- Use wait/notify on a shared object between your server and calculation class
3- Use semaphore object initialized with 0 and call acquire in your server class to wait and call release after you finish your calculations, see my answer here for an example
I wrote a thread class that checks the socket connection to the server by sending a small string every one second.
begin() method executes the thread.
After connection is lost, the thread tries to connect again.
My question is if it's ok to re-run by begin() the thread inside the run() method like I did (see below).
public void begin() {
Check = new Thread(this);
Check.start();
}
#Override
public void run() {
Thread thisThread = Thread.currentThread();
while (Check==thisThread) {
try {
oos.writeObject("a");
// oos.flush();
synchronized (this) {
while (pleaseWait) {
try {
System.out.println("waiting");
wait();
System.out.println("not waiting");
}
catch (Exception e) {
System.err.println("Thread is interrupted: "+e.getMessage());
}
}
}
sleep(1000);
} catch (Exception ex) {
v = new Visual("The connection is lost. The system will try to reconnect now.");
this.end();
try {
Server=ClientLogin.checkingServers(); //returns the reachable server string address
socket = new Socket(Server, ServerPort);
System.out.println("Connected: " + socket);
oos = new ObjectOutputStream(socket.getOutputStream());
begin();
v = new Visual("The system is reconnected.");
}
catch(UnknownHostException uhe){
System.out.println("Host unknown: " + uhe.getMessage());
v = new Visual("The system has failed to reconnected.");
}
catch (IOException ioe) {
System.out.println("The system cannot connect to servers: " + ioe.getMessage());
v = new Visual("The system has failed to reconnected.");
}
catch (Exception e) {
System.out.println("The system has failed to reconnect: " + e.getMessage());
v = new Visual("The system has failed to reconnected.");
}
}
}
}
public void end() {
Check = null;
}
I don't know any reason why that wouldn't work, but it looks kinda messy. You may have to declare Check as volatile to ensure that the loop always reads the current value, for those times when the new thread overwrites it.
IMHO a better approach would be a separate "supervisor" thread which is responsible for starting one of these threads, and then uses Thread.join() to wait for it to die, at which point it can start it up again.
In this way your main thread's logic can concentrate on exactly what it's supposed to do, without needing to have any "self awareness".
First, the code is not thread safe. The "Check" field is written by one thread but read by another, but it is not synchronised. There is no guarantee that the new started thread is going to see the updated value of "Check", i.e. the new thread will get the old thread's reference when checking "Check==thisThread" and do the wrong thing,
This particular problem can be fixed by making "Check" field volatile. It makes sure when it is updated, every thread will see the new value.
It is not "wrong" to call "begin()" in the run() method. However I wouldn't recommend it because you created a recursive call here effectively. There is a good chance you will get it wrong and fall into infinite loop. Try the simple design below. It uses a while loop instead of recursion.
package com.thinkinginobjects;
public class HeathChecker {
public void run() {
while (true) {
boolean success = checkHeath();
if (!success) {
//log and re-establish connection
} else {
Thread.sleep(1000);
}
}
}
private boolean checkHeath() {
try {
oos.writeObject("a");
return true;
} catch (Exception ex) {
return false;
}
}
}
it is ok, however why do you need to start a thread every time? Isn't it better to use Timer and TimerTask?
http://docs.oracle.com/javase/6/docs/api/java/util/TimerTask.html
http://docs.oracle.com/javase/6/docs/api/java/util/Timer.html
I am trying to keep a connection open for a multithreaded server program. When I hit a button, I want it to send a test message to all clients that are connected.
public void run() {
try {
Scanner in = new Scanner(socket.getInputStream());
PrintWriter out = new PrintWriter(socket.getOutputStream());
readUpdate(out, in);
while(true){sendUpdate(out);}
} catch (Exception e) {
e.printStackTrace();
}
}
Uses way to much CPU.
This is my sendUpdate method.
private void sendUpdate(final PrintWriter out) {
new Thread(new Runnable() {
public void run() {
if(Server.send) {
try {
if (Server.command != "idle") {
System.out.println("Sending");
out.println("!msg#" + Server.command);
out.flush();
Server.send = false;
Thread.sleep(100);
}
} catch (Exception ex) {
}
}
}
}).start();
}
If somebody can help me keep the connection open, and ready to send data, I would appreciate it.
If your server can initiate messages and so can your client, you probably want a separate thread reading and writing. One thread makes sense for request-response style communication, where you can block on the next client request, do some server-side processing, respond to the client, and then block again.
But if you need to block on two separate conditions (receiving a message from the client and you clicking the button on the server) then you should have two separate threads. Otherwise, you will find yourself needing to repeatedly wake your thread up to check if either of the conditions are true.
So create two threads, and give one your Scanner (that does the readUpdate logic) and the other your PrintWriter. This is what your output handler could look like:
public class WriteHandler implements Runnable {
private final PrintWriter out;
private final BlockingQueue<String> messageQueue = new LinkedBlockingQueue<String>();
//initialize the above in a constructor;
public void run() {
while(true) {
String nextMessageToWrite = messageQueue.poll();
out.println(nextMessageToWrite);
}
}
public void send(String message) {
messageQueue.add(message);
}
}
This uses a blocking queue, which is a much better concurrency mechanism than a check-sleep loop. Then when the button is clicked, you can just have something like this:
public void actionPerformed() {
for ( WriteHandler handler : handlers ) {
handler.send("PING!");
}
}