Why is my java program spinning after I hit server.stop(0)? - java

I wrote a basic java server class. When it handles the "shutdown" request, it calls server.stop(0) and the spins in place. Why is this happening?
I copied most of the code from this StackOverflow post.
The only significant modification to this code is that I added the server.stop(0).
Other facts: I am running this using java 8 and I am running this through IntelliJ.
package good.question.ask.questions.stackoverflow;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
public class ServerTester2
{
private HttpServer server = null;
public static void main(String[] args) throws Exception {
ServerTester2 serverTester2 = new ServerTester2();
serverTester2.start();
}
void start()
{
try {
server = HttpServer.create(new InetSocketAddress(8000), 0);
} catch (IOException e) {
e.printStackTrace();
}
server.createContext("/shutdown", new MyHandler());
server.setExecutor(null); // creates a default executor
server.start();
}
class MyHandler implements HttpHandler
{
#Override
public void handle(HttpExchange t) throws IOException
{
String response = "This is the response";
t.sendResponseHeaders(200, response.length());
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
t.close();
System.out.println("Stopping Server...");
stop();
System.out.println("Server Stopped!");
}
}
void stop()
{
server.stop(0);
}
}
Currently, the server returns a response message to the client (I tested that using postman), and then prints "Stopping Server" to the console. After that, the server object seems to be shut down, because when I send it more requests it doesn't respond to them, however, the thread running the server continues to spin.
Minimally, I expected the server to reach this line of code
System.out.println("Server Stopped!");
but it never does.
More to the point, I expected the server thread to terminate but instead, it just spins.
Why is this happening? (Do I have a deadlock in the code somewhere?)
Is there a better way to handle server shutdown (using the httpserver library)?

Related

How to terminate a thread that has been blocked for too long due to Socket.accept()?

public class Slave implements Runnable {
public ServerSocket slaveSocket;
public Slave(ServerSocket sk) {socket = sk;}
#Override
public void run() {
Socket client = slaveSocket.accept(); // slave will wait to serve a client
// more code...
Socket clientPart2 = slaveSocket.accept();
// more code...
}
}
public class Server {
public static void main(String[] args) {
// for example only, incomplete code
ServerSocket serverSocket = new ServerSocket(0); // a client connect to 8088
Slave slave = new Slave(serverSocket);
new Thread(slave).start(); // slave serve the current client, the server wait for new client
// send new slave's port to client ...
}
}
So I have a server that serves multiple clients at once. Whenever a client connects, the server will create a new Slave, send the IP/port of that slave to the client, then the client will work with the slave.
However, if the client receives the slave's address then do nothing (or quit) (Edit: it means the client and server are connected but the client do nothing, because for example the user goes for lunch) slaveSocket.accept() causes that slave Thread to run forever, which is wasteful.
I want the slave thread to exit after 30 second of waiting for slaveSocket.accept(). Since slaveSocket.accept() is blocking, I cannot do that from inside the void run().
What is the correct, clean way to solve this problem? Thank you.
Edit 1: a ServerSocket is passed to the slave because the client can have multiple processes that will connect to that slave. So it doesn't just perform one function.
If you set a timeout with setSoTimeout and no client connects, ServerSocket.accept will throw an exception. You can catch this exception.
To set a timeout of 30 seconds, use:
serverSocket.setSoTimeout(30000)
Non-blocking I/O:
Take a look at AsynchronousServerSocketChannel's accept method which returns a Future. Then the Future has a getter with timeout which can do what you are asking.
Note: you may read a related tutorial.
Then the getter will return an AsynchronousSocketChannel which can be converted back to blocking via the corresponding Channels.newInputStream and Channels.newOutputStream methods to be used with the blocking approach in the worker threads.
Blocking I/O:
I think you actually meant on how to implement a server which accepts clients sequentially and serves them in parallel, with blocking I/O. If that is the case, then you may take a look at the following example:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Objects;
public class Main {
public static class Worker implements Runnable {
private final Socket sck;
private OutputStream os;
private InputStream is;
public Worker(final Socket sck) {
this.sck = Objects.requireNonNull(sck);
}
#Override
public void run() {
try {
os = sck.getOutputStream();
is = sck.getInputStream();
//ALL the work with the client goes here, unless you need more than one connections with him.
}
catch (final IOException iox) {
System.err.println(iox);
}
finally {
try { is.close(); } catch (final IOException | RuntimeException x) {}
try { os.close(); } catch (final IOException | RuntimeException x) {}
try { sck.close(); } catch (final IOException | RuntimeException x) {}
}
}
}
public static void main(final String[] args) {
ServerSocket srv = null;
try {
srv = new ServerSocket(8088);
while (true)
new Thread(new Worker(srv.accept())).start();
}
catch (final IOException iox) {
System.err.println(iox);
}
finally {
try { srv.close(); } catch (final IOException | RuntimeException x) {}
}
}
}

Java Socket Timeout although I can connect remote via Telnet [duplicate]

I am trying to build a client/server program and it works fine. When i send a message it gets shown on the server and then it waits for a response from the server but i cant do anything while i wait for a response.
My question is : how can i wait for a response in the background while i can still send messages and just show the server message when it is sent(if it is sent).
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws IOException,UnknownHostException{
// Specify remote address and port
Socket cs = new Socket("localhost", 1337);
// Input and Output
DataInputStream dis = new DataInputStream(cs.getInputStream());
DataOutputStream dos = new DataOutputStream(cs.getOutputStream());
// Writing message to the server
String message = null;
Scanner scan = new Scanner(System.in);
while(true){
message = scan.nextLine();
if(message.equals("exit")) System.exit(0);
dos.writeUTF(message);
dos.flush();
// Check for messages from server ---> Here i wait for a message from the server but how can i wait in background without having my program freeze?
}
}
}
The simplest way in Java is to listen for server data in a separate thread.
Make the input stream final and insert something like this before the while loop reading from the console:
new Thread() {
public void run() {
try {
while (true) {
System.out.println(dis.readUTF());
}
} catch(IOException e) {
e.printStackTrace();
}
}
}.start();
This creates an anonymous subclass of Thread, which will execute the run method in the background when start is called.
When your code grows, you may want to implement the Runnable interface in a separate class and hand it in to the Thread constructor instead.

Java socket programming. How can i wait for server response in the background?

I am trying to build a client/server program and it works fine. When i send a message it gets shown on the server and then it waits for a response from the server but i cant do anything while i wait for a response.
My question is : how can i wait for a response in the background while i can still send messages and just show the server message when it is sent(if it is sent).
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws IOException,UnknownHostException{
// Specify remote address and port
Socket cs = new Socket("localhost", 1337);
// Input and Output
DataInputStream dis = new DataInputStream(cs.getInputStream());
DataOutputStream dos = new DataOutputStream(cs.getOutputStream());
// Writing message to the server
String message = null;
Scanner scan = new Scanner(System.in);
while(true){
message = scan.nextLine();
if(message.equals("exit")) System.exit(0);
dos.writeUTF(message);
dos.flush();
// Check for messages from server ---> Here i wait for a message from the server but how can i wait in background without having my program freeze?
}
}
}
The simplest way in Java is to listen for server data in a separate thread.
Make the input stream final and insert something like this before the while loop reading from the console:
new Thread() {
public void run() {
try {
while (true) {
System.out.println(dis.readUTF());
}
} catch(IOException e) {
e.printStackTrace();
}
}
}.start();
This creates an anonymous subclass of Thread, which will execute the run method in the background when start is called.
When your code grows, you may want to implement the Runnable interface in a separate class and hand it in to the Thread constructor instead.

AsynchronousServerSocketChannel.accept is only accepting a one connection

I have a small server setup where I'm trying to use event based connection sockets, so that a handler is called on each incoming connection. It works great for the first connection, but no new connections are accepted after the first one.
I just close the client connection when it comes in for simplicity. Also, yes the server is still running after the first connection, it doesn't terminate.
Here is the code:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.AsynchronousChannelGroup;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ServerTest
{
static CompletionHandler<AsynchronousSocketChannel, Object> handler =
new CompletionHandler<AsynchronousSocketChannel, Object>() {
#Override
public void completed(AsynchronousSocketChannel result, Object attachment) {
System.out.println(attachment + " completed with " + result + " bytes written");
try {
result.close();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void failed(Throwable e, Object attachment) {
System.err.println(attachment + " failed with:");
e.printStackTrace();
}
};
public static void main(String[] args) throws Exception
{
AsynchronousChannelGroup group = AsynchronousChannelGroup.withThreadPool(Executors.newSingleThreadExecutor());
System.out.println("STARTING");
AsynchronousServerSocketChannel ssc =
AsynchronousServerSocketChannel.open(group).bind(new InetSocketAddress("localhost", 9999));
System.out.println("BOUND");
ssc.accept(ssc, handler);
group.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
}
}
public abstract void accept(A attachment, CompletionHandler handler)
This method initiates an asynchronous operation to accept a connection made to this channel's socket. The handler parameter is a completion handler that is invoked when a connection is accepted (or the operation fails). The result passed to the completion handler is the AsynchronousSocketChannel to the new connection.
Read more here
This means that it initializes an asynchronous thread to accept incoming connections. This also means that it'll take the first connection and forward it to the asynchronous thread and then wait for more connections. To allow more clients to connect you must invoke an accept method inside of the overwritten completed function as well.
Here is an example,
server.accept(null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
#Override
public void completed(AsynchronousSocketChannel chan, Void attachment) {
System.out.println("Incoming connection...");
server.accept(null, this); //add this
//...
It should be noted that for every client, a new AsynchronousSocketChannel result is produced. That being said if you were to print out 'chan', it'll result in different objects.
Distinct client objects

How to prevent this Java code from hanging

I have a list of proxies to test if they are HTTP or Socks proxies, but the Java code below hangs when it calls the connection.getContent() or connection.getInputStream(). I observed that this issue occur when the proxy server fail to respond and the code blocks waiting for response from server, How can I prevent this code from hanging/blocking forever when the server fail to respond, so that the next proxy can be checked.
import java.io.*;
import java.net.*;
import java.util.*;
public class ProxyTest {
public static void main(String[] args) throws IOException {
InetSocketAddress proxyAddress = new InetSocketAddress("myproxyaddress", 1234);
Proxy.Type proxyType = detectProxyType(proxyAddress);
}
public static Proxy.Type detectProxyType(InetSocketAddress proxyAddress) throws IOException {
URL url = new URL("http://www.google.com/");
List<Proxy.Type> proxyTypesToTry = Arrays.asList(Proxy.Type.SOCKS, Proxy.Type.HTTP);
for(Proxy.Type proxyType : proxyTypesToTry) {
Proxy proxy = new Proxy(proxyType, proxyAddress);
URLConnection connection = null;
try {
connection = url.openConnection(proxy);
connection.setConnectTimeout(10000);
connection.setReadTimeout(10000);
connection.getContent();
//connection.getInputStream();
return(proxyType);
}
catch (SocketException e) {
e.printStackTrace();
}
}
return(null);
}
}
To do things in parallel, use threads.
for(Foo f : foos){
Thread t = new Thread(new Runnable(){
#Override
public void run(){
// blocking call
}
});
t.start();
}
Better yet, make use of one of the data structures in the java.util.concurrent package.
I believe there is no and simple straight solution for this. The answer depends on JDK version, implementation and runtime environment. For more details please see Java URLConnection Timeout.

Categories

Resources