I have a Socket that sends a list of Objects every few seconds to a client through ObjectOutputStream. On the server side, after every writeObject(myList) i execute flush then reset. Using VisualVM to check for memory usage, on the server there's no memory leaks, but on the client it seems that the previously read Lists are kept in memory. I tried to execute reset on the ObjectInputStream on the client side but looks like ObjectInputStream does not support this method (it throws a java.io.IOException: mark/reset not supported).
This is my server socket:
public class ConsultaBombas {
public static void inicializarServidorSocket() {
try {
ServerSocket serverSocket = new ServerSocket(5963);
Thread thread = new Thread(() -> {
while (!serverSocket.isClosed()) {
try {
final Socket socket = serverSocket.accept();
new ThreadComunicacao(socket).start();
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.setName("Consulta bombas (Inicializador)");
thread.start();
} catch (Exception e) {
e.printStackTrace();
}
}
static class ThreadComunicacao extends Thread {
private Socket socket;
public ThreadComunicacao(Socket socket) {
this.socket = socket;
setName("Consulta bombas (Comunicação) com início: " + new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(new Date()));
}
#Override
public void run() {
try {
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
while (!socket.isClosed()) {
List<Bomba> bombas = new DaoBomba().findAll();
out.writeObject(bombas);
out.flush();
out.reset();
Thread.sleep(1000);
}
} catch (SocketException e) {
if (e.getLocalizedMessage() != null && e.getLocalizedMessage().equalsIgnoreCase("Connection reset by peer: socket write error")) {
System.out.println("Cliente desconectou...");
} else {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
An this is the client (started with start() method):
public class ConsultaBombasClient {
private Socket socket;
private Thread threadConsulta;
public ConsultaBombasClient(BombasListener bombasListener, String maquinaDestino) {
threadConsulta = new Thread(() -> {
try {
Thread.currentThread().setName("Consulta Bombas");
System.out.println("Endereço bagual: "+maquinaDestino);
socket = new Socket(maquinaDestino, 5963);
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
Object leitura;
while ((leitura = in.readObject()) != null) {
List<Bomba> bombas = (List<Bomba>) leitura;
bombasListener.run(bombas);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
});
threadConsulta.setDaemon(true);
}
public void start() {
threadConsulta.start();
}
public interface BombasListener {
void run(List<Bomba> bombas);
}
}
What am i doing wrong?
garbage collection is not immediate, do you have any real memory troubles? Have you tried running the client with low -Xmx value, did you receive the OutOfMemoryError?
– user3707125
You're right, after some time when the memory gets close to the maximum heap size, it clears the objects from memory. I wasn't seeing this because i have a lot of RAM in my pc but with Xmx50m i could see this working as you said. – Mateus Viccari
Clearly bombasListener.run(), whatever it may be, is not releasing the supplied list.
NB ObjectInputStream.readObject() does not return null at end of stream. It is therefore incorrect to use this test as a termination condition for a read loop.
Related
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 would like to test the connection between a client and a server in a ScheduledExecutorService every x ms while processing received data from the distant host.
So I did something like this:
public class MyClass {
private final ScheduledExecutorService _timer = Executors.newScheduledThreadPool(1);
private Socket _connection;
public void connectToDistantHost() {
try {
_connection = new Socket();
_connection.connect(_adresseServeur);
new Thread(new Runnable() {
#Override
public void run() {
try {
//let another object know the connection is ok
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
_timer.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
testConnection();
}
}, 0, 200, TimeUnit.MILLISECONDS);
}
private void testConnection() {
//would like to peek on the socket's inputstream to know if something's wrong
}
private void myProcessing() {
while (true) {
...
//read what's inside stream
//process it in a thread
}
}
}
So, if I .read() on the Socket's inputstream it'll screw myProcessing(). I thought about wraping the inputstream in a BufferedReader and mark the buffer position before I read and then reset the position, but as the testing and the processing are in two differents thread it won't work anyway.
How can I do that? Knowing that I did it in c# without much problem:
class TraitementEnvoiClient {
...
private void testConnection(Object obj, ElapsedEventArgs args) {
_connectionIsOk = _connexionAuServeur.IsConnected();
if (!_connectionIsOk) {
tryToReconnect();
}
}
}
public static class ExtensionTcpClient {
//Credit to ElFenix: http://social.msdn.microsoft.com/Forums/en-US/c857cad5-2eb6-4b6c-b0b5-7f4ce320c5cd/c-how-to-determine-if-a-tcpclient-has-been-disconnected?forum=netfxnetcom
public static bool IsConnected(this TcpClient client) {
// Detect if client disconnected
try {
if (client.Client.Poll(0, SelectMode.SelectRead)) {
byte[] buff = new byte[1];
if (client.Client.Receive(buff, SocketFlags.Peek) == 0) {
// Client disconnected
return false;
}
}
} catch (SocketException se) {
return false;
}
return true;
}
}
Thank you
Edit: I would like to make something like that:
private static boolean isConnected(Socket client) {
try {
InputStream is = client.getInputStream();
if(is.peek() == -1) return false;
OutputStream os = client.getOutputStream();
os.write(new byte[]{}); //if it fails a IOException will trigger
} catch(SocketException se) {
return false;
} catch(IOException ioe) {
return false;
}
return true;
}
The testing is redundant. The read or write operations will return -1 if the other end closes or disconnects before or during the operation. There is no point in "testing" the connection first because it may subsequently fail during your IO operation.
See also the other answer mentioned in the comments.
This question already has answers here:
Do Java sockets support full duplex?
(2 answers)
Closed 5 months ago.
I have a Java application which is Voip. I am using the one socket to send and receive information at the same time via threads. Code is shown below ..
Socket clientSocket = sockList.accept();
OutputStream outSock = clientSocket.getOutputStream();
InputStream inSock = clientSocket.getInputStream();
new Thread( new Capture(outSock)).start();
new Thread( new PlayAudio(inSock)).start();
outSock.close();
clientSocket.close();
The problem that I'm finding is that when I write to the outputstream, it blocks on the first write. I'm sending not many bytes. Bellow is my write code.
private class Capture implements Runnable{
private OutputStream out;
public Capture(OutputStream out){
this.out = out;
}
#Override
public void run() {
try{
int numBytesRead;
TargetDataLine outLine = getMic();
outLine.open();
outLine.start();
byte[] data = new byte[outLine.getBufferSize() / 5];
byte[] test = {0x1,0x1,0x1};
while(true) {
//numBytesRead = outLine.read(data, 0, data.length);
//System.out.println(numBytesRead);
out.write(test, 0, test.length);
out.flush();
/*if(numBytesRead > 0){
out.write(data, 0, data.length);
System.out.println("C");
}*/
}
}catch(Exception ex){}
}
}
The other thread that reads the sound code is ...
private class PlayAudio implements Runnable{
private InputStream in;
public PlayAudio(InputStream in){
this.in = in;
}
#Override
public void run() {
int write;
try{
SourceDataLine inLine = getSpeaker();
inLine.open();
inLine.start();
byte[] data = new byte[inLine.getBufferSize()];
byte[] test = new byte[3];
while(true){
System.out.println(1);
//write = in.read(data, 0, data.length);
in.read(test, 0 , test.length);
System.out.println(2);
/*if(write > 0){
inLine.write(data, 0, write);
System.out.println(3);
System.out.println(write);
}*/
}
} catch(Exception ex){}
}
}
I've commented a good portion of the actual code since I'm just trying to get it to work. My write function blocks indefinitely on the first write. Is it possible this could be a problem with my threads? My only thought is that the output and input streams are sharing my socket object which may cause a deadlock or something. Please let me know whats up.
Yes you can write to a sockets input and output stream at the same time.
from do-java-sockets-support-full-duplex
Since the input stream and the output stream are separate objects within the Socket, the only thing you might concern yourself with is, what happens if you had 2 threads trying to read or write (two threads, same input/output stream) at the same time? The read/write methods of the InputStream/OutputStream classes are not synchronized. It is possible, however, that if you're using a sub-class of InputStream/OutputStream, that the reading/writing methods you're calling are synchronized. You can check the javadoc for whatever class/methods you're calling, and find that out pretty quick.
Yes you can write on socket while reading , but you have to read socket in an independent thread. I am using this concept. Here the example is (read carefully it supports mutiple client as well ) :
public class TeacherServerSocket {
private Logger logger = Logger.getLogger(TeacherServerSocket.class);
public static Map<String, TeacherServerThread> connectedTeacher = new HashMap<String, TeacherServerThread>();
ServerSocket serverSocket;;
#Override
public void run() {
// starting teacher server socket
this.serverSocket = startServer();
// if unable to to start then serverSocket would have null value
if (null != this.serverSocket) {
while (true) {
//listening to client for infinite time
Socket socket = listenToClient();
if (null != socket) {
TeacherServerThread teacherServerThread = new TeacherServerThread(socket);
Thread thread = new Thread(teacherServerThread);
thread.start();
//putting teacher ip address and teacher object into map
connectedTeacher.put(teacherServerThread.getTeacherIp(),teacherServerThread);
System.out.println("INFO: Teacher is connected with address "+ teacherServerThread.getTeacherIp());
}
}
}
}
#Override
public ServerSocket startServer() {
//port number on which teacher server will be run.
int port=12345;
try {
// throw an exception if unable to bind at given port
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("Teacher server socket started on port no :"+port);
return serverSocket;
} catch (IOException e) {
logger.error("Unable to start Teacher Server socket");
e.printStackTrace();
}
return null;
}
#Override
public Socket listenToClient() {
if (this.serverSocket != null) {
try {
// throw an exception is unable to open socket
Socket socket = this.serverSocket.accept();
return socket;
} catch (IOException e) {
logger.error("Unable to open socket for teacher");
e.printStackTrace();
}
}
else {
logger.error("TeacherServerSocket has got null value please restart the server");
}
return null;
}
#Override
public Map getConnectedDevicesMap() {
return TeacherServerSocket.connectedTeacher;
}
/**
* This method will send message to connected teacher which comes form student
* #author rajeev
* #param message, which comes form student
* #return void
* * */
#Override
public void publishMessageToClient(String message) {
if(TeacherServerSocket.connectedTeacher.size()>0){
System.out.println("Total Connected Teacher: "+TeacherServerSocket.connectedTeacher.size());
for (String teacherIp : TeacherServerSocket.connectedTeacher.keySet()) {
TeacherServerThread teacherServerThread=TeacherServerSocket.connectedTeacher.get(teacherIp);
teacherServerThread.publishMessageToTeacher(message);
}
}
}
#Override
public void stopServer() {
if (this.serverSocket != null) {
try {
serverSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
To read in an in independent thread for multiple client :
public class TeacherServerThread implements Runnable {
Logger logger=Logger.getLogger(TeacherServerThread.class);
Socket socket;
String teacherIp;
public TeacherServerThread(Socket socket) {
this.socket=socket;
this.teacherIp=socket.getInetAddress().toString();
}
#Override
public void run() {
//starting reading
ReadFromTeacherAndPublishToStudent messageReader=new ReadFromTeacherAndPublishToStudent();
Thread thread=new Thread(messageReader);
thread.start();
}
private class ReadFromTeacherAndPublishToStudent implements Runnable {
#Override
public void run() {
String message=null;
try {
BufferedReader readTeacherData=new BufferedReader(new InputStreamReader(socket.getInputStream()));
StudentServerSocket studentServerSocket=new StudentServerSocket();
//sending message to student which is read by teacher
while((message=readTeacherData.readLine())!=null){
//System.out.println("Message found : "+message);
// studentServerSocket.publishMessageToClient(message); // do more stuff here
}
// if message has null value then it mean socket is disconnected.
System.out.println("INFO: Teacher with IP address : "+teacherIp+" is disconnected");
TeacherServerScoket.connectedTeacher.remove(getTeacherIp());
if(null!=socket){
socket.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} //class
public void publishMessageToTeacher(String message){
if(this.socket!=null){
try {
PrintWriter writeMessageToTeacher=new PrintWriter(this.socket.getOutputStream());
writeMessageToTeacher.println(message);
writeMessageToTeacher.flush();
System.out.println(" Message published to teacher"+message);
}catch(Exception e){
logger.error(e.toString());
logger.error("Exception In writing data to teacher");
}
}else {
logger.error("Unable to publish message to teacher .Socket has Null value in publishMessageToTeacher");
System.out.println("ERROR: socket has null value can not publish to teacher");
}
}
public String getTeacherIp()
{
return teacherIp;
}
}
change code according to you requirement......
The reason it seems my write() is blocking is because I stupidly closed the Socket() and my input streams didn't realize it. Hence, no data is ever sent out. Silly error on my behalf.
Here is my programme, which have a two threads, one is listening user input, another is a socket:
bio = new BasicConsoleIO();
bio.assignObject(worker);
Thread b = new Thread(bio);
b.start();
Thread a = new Thread(worker);
a.start();
The worker is a socket, and the BasicConsoleIO is responsible for listening the user input
The BasicConsoleIO is something like that:
private Worker worker;
static BufferedReader reader;
#Override
public void run() {
//......Code Skip......//
if (inputString.equalsIgnoreCase("q")) {
this.applicationQuit();
}
}
public void applicationQuit(){
this.getWorker().stopWorking();
System.exit(0);
}
When it press 'q', the application will call the worker to close the socket, and quit the program, and the Worker works this way:
private ServerSocket providerSocket;
private Socket socket = null;
int port = 1234;
Worker() {
}
public void stopWorking() {
System.out.println("worker stop working");
try {
if (providerSocket != null) {
providerSocket.close();
}
if (socket != null) {
socket.close();
}
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
#Override
public void run() {
try {
providerSocket = new ServerSocket(this.port);
while (true) {
if (!providerSocket.isClosed()) {
socket = providerSocket.accept();
WorkTask wt = new WorkTask();
wt.setSocket(socket);
Thread a = new Thread(wt);
a.start();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
The worker will keep listening the request, and assign the new work task in a separate thread, the details of worktask like this:
Socket socket;
ObjectOutputStream out;
ObjectInputStream in;
Object receivedObj;
String message;
#Override
public void run() {
try {
do {
out.flush();
receivedObj = in.readObject();
//......Code Skip......//
} while (receivedObj != null
&& !receivedObj.equals(SharedConstant.SOCKET_EOF_STRING));
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException e1) {
e1.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
But When I launch the programme, and press 'q' to exit, it warns me with this error:
Please assign a port number 2333 Press 'q' to kill to programme
Waiting for connection: 2333 q worker stop working Run me anyway!
java.net.SocketException: Socket closed at
java.net.PlainSocketImpl.socketAccept(Native Method) at
java.net.PlainSocketImpl.accept(PlainSocketImpl.java:408) at
java.net.ServerSocket.implAccept(ServerSocket.java:462) at
java.net.ServerSocket.accept(ServerSocket.java:430) at
com.mydefault.package.Worker.run(Worker.java:61) at
java.lang.Thread.run(Thread.java:680)
You can see the
socket = providerSocket.accept();
is throwing an exception because in
public void stopWorking() {
// Socket won't close unless the user make it to close
// 4: Closing connection
System.out.println("worker stop working");
try {
if (providerSocket != null) {
providerSocket.close();
you closed it.
If you want to avoid this error, I have a volatile boolean closed field which I set to true and check before I report an error. i.e. ignore errors when I am closing down.