Check constantly internet connection in java - java

I am trying to check if internet is on or not constantly every 5 seconds, I wrote below code but some how it always go inside wait() and waiting infinite.
Code I wrote :
Socket socket = null;
public void checkInternetConnectivity() throws InterruptedException {
boolean reachable = false;
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
try {
socket = new Socket("xxx.xxx.xxx.x", xx);
} catch (UnknownHostException e) {
stopApp();
} catch (IOException e) {
stopApp();
}
}
}, 0, 5, TimeUnit.SECONDS);
synchronized (this) {
wait();
}
}
private void stopApp() {
System.out.println("Internet Not Available stopping app");
System.exit(0);
}
It always stuck inside below :
synchronized (this) {
wait();
}

You could do:
InetAddress.isReachable
Depending on what your needs are you should consider trying reach a specific host by
private static boolean googleIsAvailable() {
try {
final URL url = new URL("http://www.google.com");
final URLConnection connection = url.openConnection();
connection.connect();
connection.getInputStream().close();
return true;
} catch (MalformedURLException e) {
throw new RuntimeException(e);
} catch (IOException e) {
return false;
}
}
If your are communicating with a webservice the webservice should provide a GET method to check if it is available.
If you need to check constantly try somthing like
Socket s = new Socket(SERVER_ADDRESS, TCP_SERVER_PORT);
while(s.isConnected()){
//do your stuff
}
You should also check out the keepAlive Option.
But the more important question is what happen in your application if internet connection is not available anymore?
Most methods throw Exceptions if a Server is not available anymore.
You could just catch them and react on it.

Related

JAVA SOCKET realize disconnect after two writes

an app in PC using JAVA io.socket which will sends json to a server device ESP8266on TCP on LAN network
when you are connected and when disconnect sequence is executed from java it self everything is ok .
java is client and device is server , when device cuts the connection (here lets use Hercules on localhost) the java program will not being noticed and when i try to write with outputstreamwriter it dose not trig an exception , exception will be executed after at least two writes to socket after the server is being disconnected and the last two writes which was not being received by server will return success! in java. i have read other programmers use a byte send to see if connection is still alive . the same problem is there too . if i send two write each 20 seconds time in between its going to be 60 seconds before java realize server is disconnected and if i send every 1 second is going to be a lot of ATcommand interrupts for nothing .
here is my code:
public boolean Write(String data){
System.out.println("StartSending");
if(TESocket.Connected)
{
Thread write = new Thread(new Runnable() {
#Override
public void run() {
try
{
outputStreamWriter.write(data);
outputStreamWriter.flush();
}
catch (IOException e)
{
TESocket.Connected=false;
System.out.println("Faild");
System.out.println(e.getCause());
}
}
});
write.start();
return true;
}
else
{
System.out.println("Not Connected");
return false;
}
}
The TESocket is class which handles Socket using Runnable and Connected is a static boolean since there is just one socket at a time here is the connect method
public boolean Connect(){
Thread connect = new Thread(new Runnable() {
#Override
public void run() {
try {
socket= new Socket("127.0.0.1",Integer.parseInt(port));
if(socket.isConnected())
{
inputStreamReader = new InputStreamReader(socket.getInputStream());
outputStreamWriter = new OutputStreamWriter(socket.getOutputStream());
TESocket.Connected=true;
System.out.println("Connected");
}
} catch (IOException e) {
System.out.println("Faild to Connect");
e.printStackTrace();
}
}
});
connect.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(TESocket.Connected)
return true;
else
return false;
}
how can i be noticed if server is out of reach with immediately after sending the write? or is there eny event for noticing that ? maybe some king of asynchronous socket? like it was in QT (Signal Slot for Disconnect)
well By reading method and setting a timeout solved this problem , thanks to reading some post
in read if i am still connected and not receiving any data time out will be thrown which bring me back to the first lie of the while loop
if i receive data i will be bigger than zero which reader will read data and flag the rec=true so the disconnect sequence dose not take in place
if i don't receive any data and timeout dose not occurs the rec=false and exception will not be thrown so the program will o to disconnect routine
setting the timeout to 1 millisecond makes it real-time (proportional to my work) in deadline detection
public boolean Read()
{
if (TESocket.Connected)
{
try {
socket.setSoTimeout(1000);
} catch (SocketException e) {
System.out.println("Problem Timeout");
e.printStackTrace();
}
Thread read = new Thread(new Runnable() {
#Override
public void run() {
int i;
boolean rec=false;
while (true)
{
char[] reader = new char[250];
try {
//while(!inputStreamReader.ready());
i=inputStreamReader.read(reader);
if(i>0) {
System.out.println(reader);
rec=true;
}
// Thread.sleep(2500);
if(!rec)
{
System.out.println("Disconnected");
TESocket.Connected=false;
inputStreamReader.close();
outputStreamWriter.close();
socket.close();
break;
}
rec=false;
}
catch (IOException e)
{
System.out.println("Connected");
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
read.start();
}
return true;
}

Threaded Server stuck on accept() AKA How to shutdown a MulThreaded Server via client input?

Since I am stuck for this for a week now and still haven't firgured it out I try to express what I want as cleary as possible.
I have a Server which can handle Multiple Clients and communicates with them.
Whenever a client connects, the server passes the Client's request to my class RequestHandler, in which the clients commands are being processed.
If one of the clients says "SHUTDOWN", the server is supposed to cut them loose and shut down.
It doesn't work.
If only one client connects to the server, the server seems to be stuck in the accept() call and I do not know how to fix this.
THERE is already one response, but please do not take note of it, it was on a different topic which is outdated
I have two approaches and both don't seem to work.
1)If the client writes "SHUTDOWN", the shutdownFlag is set to true (in hope to exit the while loop)
2)If the client writes "SHUTDOWN", the static method shutdown() is called on the Server, which should shut him down
Below you see the implementation of my Server class, the other two classes involved are Client(all he does is connect to the Socket) and RequestHandler (this class processes the Input and writes it) .
I am 98% sure the problem lies within the Server class.
Below this is an even shorter version of the Server with just the methods without any Console outputs which might help understanding it in case you want to copy the code
public class Server {
public static final int PORTNUMBER = 8540;
public static final int MAX_CLIENTS = 3;
public static boolean shutdownFlag = false;
public static ExecutorService executor = null;
public static ServerSocket serverSocket = null;
public static void main(String[] args) {
ExecutorService executor = null;
try (ServerSocket serverSocket = new ServerSocket(PORTNUMBER);) {
executor = Executors.newFixedThreadPool(MAX_CLIENTS);
System.out.println("Waiting for clients");
while (!shutdownFlag) {
System.out.println("shutdown flag ist : " + shutdownFlag);
Socket clientSocket = serverSocket.accept();
Runnable worker = new RequestHandler(clientSocket);
executor.execute(worker);
System.out.println("Hallo");
}
if (shutdownFlag) {
System.out.println("Flag is on");
try {
executor.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
//Stop accepting requests.
serverSocket.close();
} catch (IOException e) {
System.out.println("Error in server shutdown");
e.printStackTrace();
}
serverSocket.close();
}
System.out.println("shutting down");
} catch (IOException e) {
System.out
.println("Exception caught when trying to listen on port "
+ PORTNUMBER + " or listening for a connection");
System.out.println(e.getMessage());
} finally {
if (executor != null) {
executor.shutdown();
}
}
}
public static void shutdown(){
if (shutdownFlag) {
System.out.println("Flag is on");
try {
executor.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
//Stop accepting requests.
serverSocket.close();
} catch (IOException e) {
System.out.println("Error in server shutdown");
e.printStackTrace();
}
try {
serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Server {
public static final int PORTNUMBER = 8540;
public static final int MAX_CLIENTS = 3;
public static boolean shutdownFlag = false;
public static ExecutorService executor = null;
public static ServerSocket serverSocket = null;
public static void main(String[] args) {
ExecutorService executor = null;
try (ServerSocket serverSocket = new ServerSocket(PORTNUMBER);) {
executor = Executors.newFixedThreadPool(MAX_CLIENTS);
while (!shutdownFlag) {
Socket clientSocket = serverSocket.accept();
Runnable worker = new RequestHandler(clientSocket);
executor.execute(worker);
}
if (shutdownFlag) {
try {
executor.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
serverSocket.close();
}
} catch (IOException e) {
} finally {
if (executor != null) {
executor.shutdown();
}
}
}
public static void shutdown() {
if (shutdownFlag) {
try {
executor.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
If you move the code in main into an instance method on Server (we'll say run here) you can just do new Server().run() inside main. That way you have an instance (this) to work with inside your run method.
Something like this:
class Server {
private boolean shutdownFlag = false; // This can't be static anymore.
public static final Server SERVER = new Server();
public static void main(String[] args) {
SERVER.run();
}
private void run() {
// Here goes everything that used to be inside main...
// Now you have the Server.SERVER instance to use outside the class
// to shut things down or whatever ...
}
}
This pattern isn't actually that great but better would be too long for here. Hopefully this gets you off to a good start.

Why ListView updates only if scrolled on device, but works fine on virtual device?

I recently started learning android development (am new to java as well) and I am currently working on a chat/messenger application
The problem I am facing, as the title says, is that the listview in which the messages are shown does not update on the device, unless scrolled, but it works fine on the virtual machine. I only tested on LG Optimus l5 II so far, but i need to fix this anyway.
I think it has something to do with multithreading, because this didn't happen until i added some new threads, so the adapter for listview, android manifest and rest I say are set up correctly. I can add them if it helps.
The 2 threads i added that might cause this:
Checks the connection status and if disconnected tries to reconnect.
The thread used for communicating with the server.
I tested running only with the second thread on, and the problem still occurs.
I want to specify this is the first time I try something like this (servers-client, multithreading, java, android (I'm still in college and they don`t teach us these kinds of stuff there) ), and had no documentation ahead regarding how I should set up the communication between the server and the client. This is the most efficient way I could think of.
this is at the end of onCreate:
StartConnectingRoutine(); // so you know where it all starts
and the code for it:
private void StartConnectingRoutine()
{
Thread t = new Thread()
{
#Override
public void run()
{
while(true)
{
if(!connected)
{
if( connect != null)
{
if(!connect.isAlive())
{
ConnectListener();
}
}
else
{
ConnectListener();
}
}
try {
sleep(CONNECTION_CHECK_TIME_MS); // this is set to 10000 (10 seconds)
} catch (InterruptedException e) {
Log.e("Intrerrupted", e.toString());
}
}
}
};
t.start();
}
and the connectListener():
private void ConnectListener()
{
Log.d("Connecting", "Connecting...");
connect = new Thread()
{
JSONObject info = new JSONObject();
String receivedMessage;
#Override
public void run()
{
try {
info.put("Name", user.GetName());
info.put("PORT", MY_PORT);
info.put("IPv4", getIpAddress());
} catch (JSONException e1) {
Log.e("JSON", "JSON error: " + e1.toString());
}
try
{
ServerSocket = new Socket(SERVER_IP, SERVER_PORT);
dis = new DataInputStream(ServerSocket.getInputStream());
dos = new DataOutputStream(ServerSocket.getOutputStream());
dos.writeUTF(info.toString());
dos.flush();
String response = dis.readUTF();
if(response.equals("connected"))
{
Log.d("Connect", "Connected!");
connected = true;
}
else
Log.d("Connect", "Failed to connect!");
while(connected)
{
receivedMessage = dis.readUTF();
DisplayNewMessage(new MMessage(receivedMessage, MMessage.MessageType.Received));
}
}catch(SocketException e)
{
try {
if(connected)
{
ServerSocket.close();
dis.close();
dos.close();
connected = false;
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
catch(Exception e)
{
Log.d("Connect", "Failed to connect");
Log.e("Connect", e.toString());
connected = false;
}
}
};
connect.start();
}
Fixed:
Reconnecting thread (i tried using asyncTask for this too, but it wouldn`t open the other asyncTask, even if I tried to open it from onProgressUpdate()-which it is supposed to be able to run ui thread components):
private void startConnectingRoutine()
{
Thread t = new Thread()
{
#Override
public void run()
{
Log.d("ConnectingRoutine", "Started connecting routine.");
while(true)
{
if(!connected)
{
startListener();
}
try {
sleep(CONNECTION_CHECK_TIME_MS);
} catch (InterruptedException e) {
Log.e("Intrerrupted", e.toString());
}
}
}
};
t.start();
}
Listener thread:
private void startListener()
{
new Listener().execute();
}
.
private class Listener extends AsyncTask<Long, String, Long>
{
#Override
protected Long doInBackground(Long... params) {
Log.d("Connecting...", "Connecting...");
JSONObject info = new JSONObject();
String receivedMessage;
try {
info.put("Name", user.GetName());
info.put("PORT", MY_PORT);
info.put("IPv4", getIpAddress());
} catch (JSONException e1) {
Log.e("JSON", "JSON error: " + e1.toString());
}
try
{
serverSocket = new Socket(SERVER_IP, SERVER_PORT);
dis = new DataInputStream(serverSocket.getInputStream());
dos = new DataOutputStream(serverSocket.getOutputStream());
dos.writeUTF(info.toString());
dos.flush();
String response = dis.readUTF();
if(response.equals("connected"))
{
Log.d("Connect", "Connected!");
connected = true;
}
else
Log.d("Connect", "Failed to connect!");
while(connected)
{
receivedMessage = dis.readUTF();
publishProgress(receivedMessage);
}
}
catch(Exception e)
{
Log.d("Connect", "Failed to connect");
Log.e("Connect", e.toString());
return null;
}
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
displayNewMessage(new MMessage(values[0], MMessage.MessageType.Received));
}
#Override
protected void onPostExecute(Long result) {
super.onPostExecute(result);
connected = false;
try{
if(serverSocket != null)
serverSocket.close();
if(dis != null)
dis.close();
if(dos != null)
dos.close();
}catch(Exception e)
{
Log.e("Listener", "There was a problem closing the connection: " + e.toString());
}
}
}
There are perhaps multiple things going wrong here, but two that jump out are:
You're calling DisplayNewMessage() from outside the UI thread.
You're not notifying the adapter that its dataset has changed.
I urge you to look in to better mechanisms for executing tasks in the background than simply creating a Thread. Using AsyncTasks would be a good start, but you'll need to take special care to handle tasks between configuration changes (such as rotating the device).
Furthermore, your code is very difficult to read as you capitalize your method names. This is against Java code conventions. You will make things easier for yourself by formatting your code neatly (a good IDE helps with that) and learning to follow conventions!

Code not working when running normally, but working in debug (eclipse)

I'm really confused by this: some of my code is not working when i run my program normally in eclipse, but it does wok when i run through each step separately using the debug mode.
Code:
public void showConnectDialog() {
ConnectDialog connectDialog = new ConnectDialog();
connectDialog.setVisible(true);
//Until here, code runs
while(! connectDialog.getConnected()) {};
//The next line does only run in debug
JOptionPane.showMessageDialog(connectDialog, "Connected", "Connected", JOptionPane.INFORMATION_MESSAGE);
}
The connector (is started (as a thread) as soon as the user hits 'connect' in the dialog):
private class ServerConnector implements ActionListener, Runnable {
#Override
public void actionPerformed(ActionEvent e) {
if (! IP_field.getText().equals("")) {
if (! isConnecting) {
new Thread(new ServerConnector(), "ServerConnector").start();
}
}
else {
JOptionPane.showMessageDialog(dialog,
"Enter an IP address",
"Enter IP",
JOptionPane.WARNING_MESSAGE);
}
}
#Override
public void run() {
try {
setConnecting(true);
Socket socket = connect();
if (socket != null) {
ObjectOutputStream oOut = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream oIn = new ObjectInputStream(socket.getInputStream());
if (login(oOut, oIn)) {
isConnected = true;
setConnecting(false);
}
else {
socket.close();
}
setConnecting(false);
}
}
catch (RSPException e) {
e.printStackTrace();
System.exit(1);
}
catch (Exception e) {
//If an exception occurs, setConnecting() will be true. This
//not good, so it has to be set to false
e.printStackTrace();
setConnecting(false);
}
}
private boolean login(ObjectOutputStream oOut, ObjectInputStream oIn)
throws ClassNotFoundException, IOException, RSPException {
//Send login request action:
oOut.writeObject(new LoginAction(ActionSender.CLIENT, getID(),
getPassword()));
Object obj = oIn.readObject();
if (obj instanceof LoginActionResult) {
LoginActionResult result = (LoginActionResult) obj;
if (result.getResult() == LoginResults.SUCCES) {
return true;
}
else if (result.getResult() == LoginResults.FAIL_ON_ID) {
JOptionPane.showMessageDialog(dialog,
"Invalid password or ID",
"Can't login",
JOptionPane.ERROR_MESSAGE);
return false;
}
else if (result.getResult() == LoginResults.FAIL_ON_PASSWORD) {
JOptionPane.showMessageDialog(dialog,
"Invalid password or ID",
"Can't login",
JOptionPane.ERROR_MESSAGE);
return false;
}
else if (result.getResult() == LoginResults.SERVER_FULL) {
JOptionPane.showMessageDialog(dialog,
"Couldn't connect: \n" +
"Server is full",
"Failed to connect",
JOptionPane.WARNING_MESSAGE);
return false;
}
else {
return false;
}
}
else {
System.out.println(obj);
throw new RSPException("Server is not following the protocol.");
}
}
private void setConnecting(boolean connecting) {
if (connecting) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
connectButton.setEnabled(false);
}
});
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
connectButton.setText("Connecting...");
}
});
}
else {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
connectButton.setText("Connect");
}
});
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
connectButton.setEnabled(true);
}
});
}
isConnecting = connecting;
}
private String getAddressFromTextField() {
return IP_field.getText();
}
private InetAddress getInetAddress(String fullAddress) {
try {
if (fullAddress.contains(":")) {
String[] splitAddress = fullAddress.split(":");
return InetAddress.getByName(splitAddress[0]);
}
else {
return InetAddress.getByName(fullAddress);
}
}
catch (UnknownHostException e) {
return null;
}
}
private int getPort(String fullAddress) {
try {
String[] splittedAddress = fullAddress.split(":");
return Integer.valueOf(splittedAddress[1]);
}
catch (NumberFormatException ex) {
return -1;
}
catch (NullPointerException
| ArrayIndexOutOfBoundsException
| PatternSyntaxException ex) {
//Returning default port value: 25566, because no port was given
return 25566;
}
}
#SuppressWarnings("resource")
private Socket connect() {
Socket socket = null;
InetAddress address = null;
if ((address = getInetAddress(getAddressFromTextField())) == null) {
return null;
}
int port = getPort(getAddressFromTextField());
try {
socket = new Socket(address, port);
}
catch (ConnectException e ) {
Socket retrySocket = null;
if ((retrySocket = retryConnect(address, port)) == null) {
JOptionPane.showMessageDialog(dialog,
"Connection timed out",
"Failed to connect",
JOptionPane.ERROR_MESSAGE);
setConnecting(false);
}
else {
socket = retrySocket;
}
}
catch(IOException e) {
e.printStackTrace();
}
return socket;
}
private Socket retryConnect(InetAddress address, int port) {
Thread waitThread = new Thread(new Runnable() {
#Override
public void run() {
try {
//Will wait 15(000) (milli)seconds before stopping with
//trying to connect.
//One second (1000 millis) is for debugging and testing
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
});
waitThread.start();
while (waitThread.isAlive()) {
try {
return new Socket(address, port);
}
catch (ConnectException e) {
//Do nothing, will re-attempt to connect.
}
catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
private String getID() {
return ID_field.getText();
}
private String getPassword() {
if (getID().equals("master")) {
return "masterPassword";
}
else {
return new String(passwordField.getPassword());
}
}
}
getConnected() returns true as soon as it's connected to the server. The connector is running on a separate thread.
EDIT: I tried to put code in the getConnected() while block, and then it works. Why does it works then and not else?
I had the same Problem, but with some more specification. The code was working fine in 32bit but I had this issue in 64bit (I am using native library so I need to maintain both).
The solution I found is to add Thread.sleep() in the while loop. I don't know why it works, so your guess is as good as mine.
A better solution would probably to implement an Observer Pattern instead of having an infinite loop. But that would require some re-factoring.
Using Thread.sleep(), as the other answers have suggested, should solve the problem but it is not a very good approach. Instead, we should be using Thread.yield().
Why yield and not sleep?
Refer:
Difference between Thread.Sleep(0) and Thread.Yield() and Are Thread.sleep(0) and Thread.yield() statements equivalent?
Why this works?
When we just run the threads, the OS puts them to "idle" state and when it is expected to "wake-up", it does not. On the other hand, in debug mode, we have a controlled environment. The OS has little control over it as everything goes on step-by-step, slowly. If we run the debug a few times without any break-points, after a few successful runs, we should see the same effect.
I had a very similar problem with a "while" loop that wouldn't run and that loop was my main routine. How I got the loop to run was that the very first thing that was done in the loop was a sleep:
try
{Thread.sleep(0);}
catch (Exception e)
{e.printStackTrace();}
This was enough to get everything going.
I had same problem in UIAutomator with UiObject2 wait(Until.findObject(),20) .
Thread.yield() - works for me

Java: Synchronizing socket input

My first attempt at writing a client for a php socket server and I'm running into a little trouble and I'm sort of being flooded with info!
With the server, we want an open connection, I want my client end to wait until it receives data before notifying the thread to start parsing the input-stream. Is this achievable without using a loop? I'd rather be able to call lock.notify().
I was also looking at NIO, is this a viable option for what I want?
Here's the code I have so far, but again, I'm just trying to avoid the for(;;) and maybe even queue the received messages as they will most likely just be JSON
Thread serverRecieve = new Thread(new Runnable() {
#Override
public void run() {
try {
for (;;) {
if (in != null) {
String line;
while ((line = in.readLine()) != null) {
sout(line);
}
} else {
sout("inputstream is null! Waiting for a second to test again");
}
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(WebManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
} catch (IOException ex) {
Logger.getLogger(WebManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
Thanks guys!
PS: I did look through A LOT of socket threads on here but decided it would be easier just to ask what I need.
I think you can use a while loop and put a condition using in != null as:
while(in == null){
//wait for a second before checking the in stream again
try {
sout("inputstream is null! Waiting for a second to test again");
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(WebManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
//now your in is available. Read the data and proceed
String line = null;
while ((line = in.readLine()) != null) {
sout(line);
}
The first while loop will terminate as soon in stream is available.
How about creating dedicated subtype of Runnable for reading from socket, like this:
class Reader implements Runnable {
private final Socket socket;
private volatile boolean stopped;
Reader(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
while (true) {
int in = socket.getInputStream().read();
// process in here
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (!stopped) socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void stop() {
try {
stopped = true;
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Client {
private volatile Reader reader;
void start() {
reader = new Reader(new Socket(serverHost, serverPort));
Thread readerThread = new Thread(reader, "Reader-thread");
readerThread.start();
}
void stop() {
Reader reader = this.reader;
// reader.stop() will close socket making `run()` method finish because of IOException
// reader.socket is final, thus we have proper visibility of it's values across threads
if (reader != null) reader.stop();
}
}

Categories