I seem to have an unusual problem that I can't understand the root cause to.
I am using a ServerSocket to handle connections to a server I'm writing. The ServerSocket accepts connections in it's own thread, and can be controlled from the main thread via isAccepting and isActive variables I set up.
What should happens:
Server starts and is accepting connections (via putty). I use a command to close the server socket. The socket closes and the thread idles (I notice this causes a SocketException that I catch). I use a command to open a new server socket and it accepts connections again. I'm able to connect and can exit the application via a command that shuts down the socket and exits the loop accepting connections
What happens:
Server starts and is accepting connections (via putty). I use a command to close the server socket. The socket closes and the thread idles(I notice this causes a SocketException that I catch). I use a command to open a new server socket and that's where the thread hangs. It does not print out any debug info that's in the code, nor does it responde to opening/closing the ServerSocket. using the Exit command hangs the application on the exit routine. Funny thing is, if I set a breakpoint anywhere in the thread code, it unstucks and completes, exiting.
TL;DR - closing the socket jams the thread until I place a breakpoint, after which the code executes normally.
Tried exporting into an executable JAR and the application hangs on exit, just like in Eclipse.
Relevant parts of code below:
public class ConnectionManager extends Thread implements IEverfreeManager {
private final int defaultPort = 8002;
private boolean isAccepting = true;
private boolean isActive = true;
private static ConnectionManager instance;
private ServerSocket serverSocket;
private int portNumber = defaultPort;
private Socket workSocket;
public static ConnectionManager instance(){
if (instance == null)
instance = new ConnectionManager();
return instance;
}
public ConnectionManager() {
}
public boolean isAccepting() {
return isAccepting;
}
public void setAccepting(boolean isAccepting) {
this.isAccepting = isAccepting;
try{
if (!isAccepting && !serverSocket.isClosed()){
serverSocket.close();
System.out.println("Closed server on port "+portNumber);
} else{
serverSocket = new ServerSocket(portNumber);
System.out.println("Server on port "+portNumber+" is now accepting connections");
}
}catch(Exception e){
System.out.println("failed to stop accepting");
e.printStackTrace();
}
}
public boolean isActive() {
return isActive || isAlive();
}
public void setActive(boolean isActive) {
this.setAccepting(isActive);
this.isActive = isActive;
}
public int getPortNumber() {
return portNumber;
}
public void setPortNumber(int portNumber) {
this.portNumber = portNumber;
}
private int getNewConnectionId(){
return ++connectionIdCounter;
}
#Override
public void run() {
super.run();
try {
System.out.println("Starting up Connection Manager");
System.out.println("Starting server on port "+portNumber);
serverSocket = new ServerSocket(portNumber);
System.out.println("Server running and ready to accept players");
while (isActive){
if (isAccepting){
try{
System.out.println("Waiting for connection...");
workSocket = serverSocket.accept();
System.out.println("Connected with "+workSocket.getInetAddress());
int id = getNewConnectionId();
} catch (SocketException e){
System.out.println("Notice: "+e.getMessage());
}
}
}
}catch(Exception e) {
e.printStackTrace();
}
}
#Override
public void closeManager() {
setActive(false);
}
Using setAccepting(false) and then setAccepting(true) doesn't produce the
System.out.println("Waiting for connection...");
message until I put a breakpoint in the code.
Using closeManager() after setAccepting(false) produces the same results.
Using just closeManager() without touching setAccepting() exits gracefully (despite having the procedure activated during shutdown)
Any insight would be very appreciated
There's nothing thread-safe in this class. There are very fundamental problems with almost every function.
Both isAccepting and isActive both need to be either volatile or be modified in a synchronized manner to be thread-safe. If another thread is calling functions that mutate these fields and you have your run method already looping over them you may get unpredictable results. Attempting to view boolean flags that have no memory visibility guarantees is always a bad idea.
setAccepting() has a race condition where your run() thread may attempt to listen on a socket that is immediately about to be closed.
The singleton ConnectionMananger instance could have multiples be created. In your case your constructor does nothing but it's generally safer to not have to create instances. Use double checked locking to implement this so only one instance will ever be created.
Your immediate problem could likely be 'fixed' by making both the is* member fields volatile but like I said you still have too many other issues in this class that it would be complete safe to use in a multithreaded environment. In addition, catching Exception and simply printing is usually wrong. And you usually want to subclass runnable and pass that to the thread constructor rather than creating a subclass of thread.
Related
I have received some code through a school project and I'm failing to understand the purpose of the use of threading in this scenario. The project requires use of a multi threading server to pass. I have the following thread implementation which of a new instance is created every time a new client connects.
The problem is that they are not using the run-method, in my understanding the thread exists when it finishes running the run-method. But even after the thread should have finished running it manages to send further the messages from the propertyStateListener. Why does this work and does this really count as a multi-threaded server?
Starts an instance of the ClientHandler every time a new client connects:
#Override
public void run() {
while (true) {
MessageProducer mp;
try {
Socket socket = serverSocket.accept();
new ClientHandler(socket).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The actual ClientHandler:
private class ClientHandler extends Thread implements PropertyChangeListener {
private Socket socket;
private ObjectInputStream ois;
private ObjectOutputStream oos;
private Message messagerecieved;
public ClientHandler(Socket socket) throws IOException {
this.socket = socket;
oos = new ObjectOutputStream(socket.getOutputStream());
ois = new ObjectInputStream(socket.getInputStream());
messageManager.registerListener(this);
}
#Override
public void propertyChange(PropertyChangeEvent evt) {
messagerecieved = (Message) evt.getNewValue();
try {
oos.writeObject(messagerecieved);
oos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
}
}
The problem is that they are not using the run-method, in my understanding the thread [exits] when it finishes running the run-method. But even after the thread should have finished running it manages to send further the messages from the propertyStateListener.
You are correct that the code is confusing for sure. They are creating a thread with each instance of ClientHandler but there is no run() method so the thread immediately exits after start() is called. The code would actually still work if ClientHandler did not extend thread.
Why does this work
It is the messageManager thread which is calling back to the ClientHandler.propertyChange(...) method which writes the results back to the socket, not the ClientHandler thread.
does this really count as a multi-threaded server?
There certainly are 2 threads at work here because you have the socket-accept thread and the messageManager thread. Whether or not this is a "multi-threaded server" depends on the assignment I guess. Certainly if there was supposed to be a thread per client then this code does not do that.
I have gone through so many tutorials on Synchronization now that my head is spinning. I have never truly understood it :(.
I have a Java server(MainServer), that when a client connects creates a new thread(ServerThread) with a DataOutputStream.
The client talks to the ServerThread and the ServerThread responds. Every now and then the MainServer will distribute a message to all clients utilizing each ServerThread's DataOutputStream object.
I am quite certain that every now and then my issue is because both the MainServer and ServerThread are trying to send something to the client at the same time. Therefore I need to lock on the DataOutputStream object. For the life of me I cannot understand this concept any further. Every example I read is confusing.
What is the correct way to handle this?
ServerThread's send to client method:
public void replyToOne(String reply){
try {
commandOut.writeUTF(reply);
commandOut.flush();
} catch (IOException e) {
logger.fatal("replyToOne", e);
}
logger.info(reply);
}
MainServer's distribute to all clients method:
public static void distribute(String broadcastMessage){
for (Map.Entry<String, Object[]> entry : AccountInfoList.entrySet()) {
Object[] tmpObjArray = entry.getValue();
DataOutputStream temporaryCOut = (DataOutputStream) tmpObjArray[INT_COMMAND_OUT]; //can be grabbed while thread is using it
try {
temporaryCOut.writeUTF(broadcastMessage);
temporaryCOut.flush();
} catch (IOException e) {
logger.error("distribute: writeUTF", e);
}
logger.info(broadcastMessage);
}
}
I am thinking I should have something like this in my ServerThread class.
public synchronized DataOutputStream getCommandOut(){
return commandOut;
}
Is it really that simple? I know this has likely been asked and answered, but I don't seem to be getting it still, without individual help.
If this were me.....
I would have a LinkedBlockingQueue on each client-side thread. Then, each time the client thread has a moment of idleness on the socket, it checks the queue. If there's a message to send from the queue, it sends it.
Then, the server, if it needs to, can just add items to that queue, and, when the connection has some space, it will be sent.
Add the queue, have a method on the ServerThread something like:
addBroadcastMessage(MyData data) {
broadcastQueue.add(data);
}
and then, on the socket side, have a loop that has a timeout-block on it, so that it breaks out of the socket if it is idle, and then just:
while (!broadcastQueue.isEmpty()) {
MyData data = broadcastQueue.poll();
.... send the data....
}
and you're done.
The LinkedBlockingQueue will manage the locking and synchronization for you.
You are on the right track.
Every statement modifying the DataOutputStream should be synchronized on this DataOutputStream so that it is not concurrently accessed (and thus do not have any concurrent modification):
public void replyToOne(String reply){
try {
synchronized(commandOut) { // writing block
commandOut.writeUTF(reply);
commandOut.flush();
}
} catch (IOException e) {
logger.fatal("replyToOne", e);
}
logger.info(reply);
}
And:
public static void distribute(String broadcastMessage){
for (Map.Entry<String, Object[]> entry : AccountInfoList.entrySet()) {
Object[] tmpObjArray = entry.getValue();
DataOutputStream temporaryCOut = (DataOutputStream) tmpObjArray[INT_COMMAND_OUT]; //can be grabbed while thread is using it
try {
synchronized(temporaryCOut) { // writing block
temporaryCOut.writeUTF(broadcastMessage);
temporaryCOut.flush();
}
} catch (IOException e) {
logger.error("distribute: writeUTF", e);
}
logger.info(broadcastMessage);
}
}
Just putting my 2 cents:
The way I implement servers is this:
Each server is a thread with one task only: listening for connections. Once it recognizes a connection it generates a new thread to handle the connection's input/output (I call this sub-class ClientHandler).
The server also keeps a list of all connected clients.
ClientHandlers are responsible for user-server interactions. From here, things are pretty simple:
Disclaimer: there are no try-catches blocks here! add them yourself. Of course you can use thread executers to limit the number of concurrent connections.
Server's run() method:
#Override
public void run(){
isRunning = true;
while(isRunning){
ClientHandler ch = new ClientHandler(serversocket.accept());
clients.add(ch);
ch.start();
}
}
ClientHandler's ctor:
public ClientHandler(Socket client){
out = new ObjectOutputStream(client.getOutputStream());
in = new ObjectInputStream(client.getInputStream());
}
ClientHandler's run() method:
#Override
public void run(){
isConnected = true;
while(isConnected){
handle(in.readObject());
}
}
and handle() method:
private void handle(Object o){
//Your implementation
}
If you want a unified channel say for output then you'll have to synchronize it as instructed to avoid unexpected results.
There are 2 simple ways to do this:
Wrap every call to output in synchronized(this) block
Use a getter for output (like you did) with synchronized keyword.
I actually had a much bigger question, but I reduced it:
How does Socket.connect() behave when close() was called on that Socket before, but no connection attempt was made previously?
Multithreading/Threads is related, because I have one thread that is doing the connecting and one that invokes this and may abort the connection before being connected. Due to the joys of multithreading, an abort could be made before connect() is actually called, even if I synchronized-check with a boolean before. (lets say the abort code gets called just before connect() is doing its work, but after connect() was called - at the beginning of the method for example.)
Some code, heavily reduced:
public class Connecter {
private Socket socket;
public void connect() {
// start the connecting thread, synchronized
}
public void abort() {
// synchronized as well: closes the socket, nulls the refernce, sets a boolean value to true (aborted)
}
private class ConnectingThread extends Thread {
public void run() {
try {
// synchronized: create a socket object and set stuff such as TCP_NODELAY
socket.connect(new InetSocketAddress(ip, port));
// handle stuff afterwards, synced of course
} catch (Exception ex) {
// wow. such exceptions. much handling.
}
}
}
}
How does Socket.connect() behave when close() was called on that Socket before, but no connection attempt was made previously?
It will throw a SocketException with the text 'Socket is closed.'
I'm writing a client/server application in Java using sockets. In the server, I have a thread that accepts client connections, this thread runs indefinitely. At some point in my application, I want to stop accepting client connection, so I guess destroying that thread is the only way. Can anybody tell me how to destroy a thread?
Here's my code:
class ClientConnectionThread implements Runnable {
#Override
public void run() {
try {
// Set up a server to listen at port 2901
server = new ServerSocket(2901);
// Keep on running and accept client connections
while(true) {
// Wait for a client to connect
Socket client = server.accept();
addClient(client.getInetAddress().getHostName(), client);
// Start a new client reader thread for that socket
new Thread(new ClientReaderThread(client)).start();
}
} catch (IOException e) {
showError("Could not set up server on port 2901. Application will terminate now.");
System.exit(0);
}
}
}
As you can see, I have an infinite loop while(true) in there, so this thread will never stop unless somehow I stop it.
The right way to do this would be to close the server socket. This will cause the accept() to throw an IOException which you can handle and quit the thread.
I'd add a public void stop() method and make the socket a field in the class.
private ServerSocket serverSocket;
public ClientConnectionThread() {
this.serverSocket = new ServerSocket(2901);
}
...
public void stop() {
serverSocket.close();
}
public void run() {
while(true) {
// this will throw when the socket is closed by the stop() method
Socket client = server.accept();
...
}
}
Generally you don't. You ask it to interrupt whatever it is doing using Thread.interrupt().
A good explanation of why is in the Javadoc.
From the link:
Most uses of stop should be replaced by code that simply modifies some
variable to indicate that the target thread should stop running. The
target thread should check this variable regularly, and return from
its run method in an orderly fashion if the variable indicates that it
is to stop running. (This is the approach that the Java Tutorial has
always recommended.) To ensure prompt communication of the
stop-request, the variable must be volatile (or access to the variable
must be synchronized).
It should be noted that in all situations where a waiting thread doesn't respond to Thread.interrupt, it wouldn't respond to Thread.stop either.
For your specific situation you will have to call serverSocket.close, since it does not respond to Thread.interrupt.
I create a class that allows me to open a single instance of my Java program. It uses a daemon thread that open a ServerSocket. if the TCP Port was already taken throws an exception at instantiation time.
The code works normally under linux and windows.
Here is the code i am using:
public class SingleInstaceHandler extends Thread {
private static final Logger log = Logger.getLogger(IEPLC_Tool.class);
private boolean finished = false;
#SuppressWarnings("unused")
private ServerSocket serverSocket;
/*
* Constructor
* Generate the server socket.
* If the TCP door was busy throws IOException.
*/
public SingleInstaceHandler() throws IOException {
#SuppressWarnings("unused")
ServerSocket serverSocket = new ServerSocket(44331);
this.setDaemon(true);
this.start();
log.info("Server socket initialized"); //if commented out it works
}
public void run() {
synchronized (this) {
while (!finished) {
try {
log.debug("Server socket goes to sleep");
this.wait();
log.debug("Server socket waken up");
} catch (InterruptedException e) {
log.debug("ERROR while sending SocketThread2 in wait status");
e.printStackTrace();
System.exit(-1);
}
log.info("Server socket end");
}
}
}
public synchronized void shutdown() {
log.debug("SingleInstaceHandler shutdown() caled");
finished = true;
notifyAll();
}
}
Sometimes instead the port is not kept busy... any idea?
UPPENDED AFTER FURTHER TESTS:
running many other tests. it seams that if the port is taken by something like another SW instance new ServerSocket(44331); throws an exception but sometimes even if the port is not taken for some reason it can not get this resource. in this case no exception is launched and i can open as many instance as i want of my application. maybe i should do some other operation to force the thread to lock the port...
any idea?
Thanks,
Ste
As you are not keeping a reference to the ServerSocket it will be eligible for GC. If you are using the Oracle JDK the socket will be closed when it is GCed (java.net.PlainSocketImpl).
I do feel a bit stupid in posting an answer to my question... well.. my code has a bug that took me long to figure out:
the problem is that in te constructor i do:
ServerSocket serverSocket = new ServerSocket(44331);
instead of:
this.serverSocket = new ServerSocket(44331);
I did not notice it before... basicaly the bug was that I was declaring a local socket within the constructor. When the constructur procedure was terminated the socket was released or not depending on the Garbadge Collector. Behavior was quite random. Funny part was that plenty of time calling/not calling the logger was enougth to make the Garbadge collector starting or not. It took me quite a while in noticing the mistake.
furthermore it's better to put a :
this.serverSocket.close() after the wait.
Thans for helping anyway!
Cheers,
Ste