I am developing a simple Java class with a thread that creates a Client socket that connects to a server.
This thread retrieves bytes via a BlockingQueue
then sends them to the server, then retrieves bytes again, etc.
My problem is that I don't know on which condition the while structure should loop. I would actually like to be able to retrieve a "disconnect" from the server without the server having to send data indicating a disconnect.
How can I solve this?
Here is my code:
public class ClientThread extends Thread {
private static final String TAG = "ClientThread";
private Socket socket = null;
private OutputStream out = null;
private BlockingQueue<Message> queue = null;
private static final int SERVERPORT = 8080;
private static final String SERVER_IP = "localhost";
public ClientThread(BlockingQueue<Message> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
//send a request to connect to the server is listening on machine 'localhost', port 8080
socket = new Socket(serverAddr, SERVERPORT);
//create output stream to send data to the server
out = socket.getOutputStream();
while (/* a condition */) {
//Do some work on socket
}
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
protected void finalize() throws Throwable {
try {
socket.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
CodePudding user response:
I wrote a simple Client-Server communication to showcase how you can solve that:
package stackoverflow.multithreadingfiles.servlets;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TestSocket {
static public final int PORT = 12345;
public static void main(final String[] args) {
runServerThread();
sleep(2000);
runClientThread();
}
private static void sleep(final int pMS) {
try {
Thread.sleep(pMS);
} catch (final InterruptedException e) { /* */ }
}
private static void runServerThread() {
final Thread t = new Thread(() -> runServer());
t.setName("Server Thread");
t.start();
}
private static void runClientThread() {
final Thread t = new Thread(() -> runClient());
t.setName("Client Thread");
t.setDaemon(true);
t.start();
}
private static void runServer() {
System.out.println("Server Thread starting");
try (final ServerSocket ss = new ServerSocket(PORT);) {
while (true) {
System.out.println("Server Thread waiting for new connection...");
try (final Socket socket = ss.accept();) {
System.out.println("Server Thread connected...");
while (!socket.isClosed()) {
socket.getOutputStream().write((int) (Math.random() * 100));
sleep((int) (Math.random() * 1000));
if (Math.random() < 0.1) {
System.out.println("Server Thread disconnecting...");
// socket.close(); you can commemt that in or out, will not have any effect
break;
}
}
} // auto-closes Socket here
}
} catch (final IOException e) {
e.printStackTrace();
} finally {
System.out.println("Server Thread ended.");
}
}
private static void runClient() {
System.out.println("Client Thread starting");
try (Socket s = new Socket("localhost", PORT);
InputStream sis = s.getInputStream()) {
final byte[] buffer = new byte[256];
while (!s.isClosed()) { // s.isClosed() will actually NOT indicate if Server closed the Socket, so you can just write while(true)
final int bytesRead = sis.read(buffer);
System.out.print("Client received " bytesRead " bytes: ");
for (int i = 0; i < bytesRead; i ) {
System.out.print("\t" buffer[i]);
}
System.out.println();
if (bytesRead < 0) { // actually value will be -1 if socket is closed. Same if you read a single byte with sis.read();
// this check usually comes directly after reading from the socket, but I wanted to showcase the -1 data length you'll get
System.out.println("Client noticed that connection was closed.");
break;
}
}
} catch (final Exception e) {
e.printStackTrace();
} finally {
System.out.println("Client Thread ended.");
}
}
}
CodePudding user response:
Try using Socket#isClosed()
, or a global variable, that is set when the client disconnects.