httpClient connection not closing - java

Version
vert.x core: 3.3.0
Context
Am just trying to run http client in core examples io.vertx.example.core.http.simple.Client.
While running this example its found that the established connection not closing after completion of request.
Server side I didnt see any issue. Since while trying with jmeter and server its working fine. So I think that the problem is in the HttpClient.
Anyone can help me on this?
Thanks in advance.
Steps to reproduce
running io.vertx.example.core.http.simple.Server code
running io.vertx.example.core.http.simple.Client code
Extra
The following shown even after the request and response is ended. while giving
LINUX
lsof -i -P
java 32551 USER 223u IPv4 16264097 0t0 TCP localhost:8080->localhost:26980 (ESTABLISHED)
java 32634 USER 218u IPv4 16264087 0t0 TCP localhost:26980->localhost:8080 (ESTABLISHED)
WINDOWS
TCP 127.0.0.1:8080 FSSCHND12957:56893 ESTABLISHED
TCP 127.0.0.1:56893 FSSCHND12957:8080 ESTABLISHED
Tried in both LINUX and WINDOWS system.
Client Code
package io.vertx.example.core.http.simple;
import io.vertx.core.AbstractVerticle;
import io.vertx.example.util.Runner;
/*
#author Tim Fox
*/
public class Client extends AbstractVerticle {
// Convenience method so you can run it in your IDE
public static void main(String[] args) {
Runner.runExample(Client.class);
}
#Override
public void start() throws Exception {
vertx.createHttpClient().getNow(8080, "localhost", "/", resp -> {
System.out.println("Got response " + resp.statusCode());
resp.bodyHandler(body -> {
System.out.println("Got data " + body.toString("ISO-8859-1"));
});
});
}
}
Server Code
package io.vertx.example.core.http.simple;
import io.vertx.core.AbstractVerticle;
import io.vertx.example.util.Runner;
/*
#author Tim Fox
*/
public class Server extends AbstractVerticle {
// Convenience method so you can run it in your IDE
public static void main(String[] args) {
Runner.runExample(Server.class);
}
#Override
public void start() throws Exception {
vertx.createHttpServer().requestHandler(req -> {
req.response().putHeader("content-type", "text/html").end("
Hello from vert.x!
");
}).listen(8080);
}
}

We have to close the httpClient which we normally do in java. Only end() is not closing the connection. httpClient.close() is required.... This solved my issue..
Modified code:
public class Client extends AbstractVerticle {
// Convenience method so you can run it in your IDE
public static void main(String[] args) {
Runner.runExample(Client.class);
}
#Override
public void start() throws Exception {
HttpClient httpClient = vertx.createHttpClient().getNow(8080, "localhost", "/", resp -> {
System.out.println("Got response " + resp.statusCode());
resp.bodyHandler(body -> {
System.out.println("Got data " + body.toString("ISO-8859-1"));
httpClient.close();
});
});
}
}

Related

Java create/overwrite http server

I'm creating a plugin on a certain platform (the details are irrelevant) and need to create a HTTP endpoint. In normal circumstances you'd create a http server and stop it whenever you're done using it or when the application stops, however, in my case I can't detect when the plugin is being uninstalled/reinstalled.
The problem
When someone installs my plugin twice, the second time it will throw an error because I'm trying to create a http server on a port which is already in use. Since it's being reinstalled, I can't save the http server on some static variable either. In other words, I need to be able to stop a previously created http server without having any reference to it.
My attempt
I figured the only way to interact with the original reference to the http server would be to create a thread whenever the http server starts, and then overwrite the interrupt() method to stop the server, but somehow I'm still receiving the 'port is already in use' error. I'm using Undertow as my http server library, but this problem applies to any http server implementation.
import io.undertow.Undertow;
import io.undertow.util.Headers;
public class SomeServlet extends Thread {
private static final String THREAD_NAME = "some-servlet-container-5391301";
private static final int PORT = 5839;
private Undertow server;
public static void listen() { // this method is called whenever my plugin is installed
deleteExistingServer();
new SomeServlet().start();
}
private static void deleteExistingServer() {
for (Thread t : Thread.getAllStackTraces().keySet()) {
if (t.getName().equals(THREAD_NAME)) {
t.interrupt();
}
}
}
#Override
public void run() {
createServer();
}
#Override
public void interrupt() {
try {
System.out.println("INTERRUPT");
this.server.stop();
} finally {
super.interrupt();
}
}
private void createServer() {
this.server = Undertow.builder()
.addHttpListener(PORT, "localhost")
.setHandler(exchange -> {
exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");
exchange.getResponseSender().send("Hello World!");
})
.build();
this.server.start();
}
}
Desired behaviour
Whenever listen() is called, it will remove any previously existing http server and create a new one, without relying on storing the server on a static variable.
You could try com.sun.net.httpserver.HttpServer. Use http://localhost:8765/stop to stop and 'http://localhost:8765/test' for test request:
import com.sun.net.httpserver.HttpServer;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
public class TestHttpServer {
public static void main(String[] args) throws IOException {
final HttpServer server = HttpServer.create();
server.bind(new InetSocketAddress(8765), 0);
server.createContext("/test", httpExchange -> {
String response = "<html>TEST!!!</html>";
httpExchange.sendResponseHeaders(200, response.length());
OutputStream os = httpExchange.getResponseBody();
os.write(response.getBytes());
os.close();
});
server.createContext("/stop", httpExchange -> server.stop(1));
server.start();
}
}

Secure WebSocket server in Android

I am using the AndroidAsync library from GitHub that is provided by koush. I need this library to create a WebSocket server and I was able to create it.
private static List<WebSocket> webSockets = new ArrayList<WebSocket>();
private static AsyncHttpServer httpServer = new AsyncHttpServer();
Here's the implementation:
public static void createWebSocket() {
httpServer.websocket("/", new AsyncHttpServer.WebSocketRequestCallback() {
#Override
public void onConnected(final WebSocket webSocket, AsyncHttpServerRequest request) {
webSockets.add(webSocket);
webSocket.setClosedCallback(new CompletedCallback() {
#Override
public void onCompleted(Exception ex) {
Log.d(TAG, "onCompleted");
}
});
webSocket.setStringCallback(new WebSocket.StringCallback() {
#Override
public void onStringAvailable(String s) {
Log.d(TAG, "onStringAvailable");
}
});
}
});
httpServer.listen(8080);
}
This implementation works completely fine.
But I want to use the wss protocol where I can use a JKS (Java KeyStore) certificate for the websocket.
Is there any way to do this? If not with this library, is there any other library I can use? Any example would be really appreciated.
Thank you!!
try this one. I haven't used it. However, it says it supports Java servers and Android clients with support for wss. Good luck!
Honestly, I don't know that I am right. I just happened into this.
Do you think you could do it with NanoHTTPD for java?
I imagine the basic structure is:
MyHTTPDTask
import java.io.IOException;
import java.util.Map;
import fi.iki.elonen.NanoHTTPD;
class MyHTTPDTask extends AsyncTask {
private MyServer mHTTPD;
#Override
protected Object doInBackground(Object... params) {
mHTTPD = new MyServer();
mHTTPD.makeSecure(NanoHTTPD.makeSSLSocketFactory(R.string.keystore.jks, "password".toCharArray()), null);
}
}
MyServer
import java.io.IOException;
import fi.iki.elonen.NanoHTTPD;
public class MyServer extends NanoHTTPD {
private final static int PORT = 8080;
public MyServer() throws IOException {
super(PORT);
start();
System.out.println( "\nRunning! Point your browers to http://localhost:8080/ \n" );
}
#Override
public Response serve(IHTTPSession session) {
String msg = "<html><body><h1>Hello server</h1>\n";
msg += "<p>We serve " + session.getUri() + " !</p>";
return newFixedLengthResponse( msg + "</body></html>\n" );
}
}
For the server side, why don't you use the standard API, javax.websocket? It's a part of Java EE.
For the Android side, see "Which WebSocket library to use in Android app?".

How to import the Gottox/socket.io-java-client api in current Eclipse Android Project?

I'm trying to write a JavaScript server running on node.js using Socket.io that communicates with the client which is my android app (java class). Since I need a combination of a JS server and java client that utilizes the Socket.io (or any other efficient websockets) framework, I found the Gottox/socket-io.-java-client implementation that seemed like it might do the job.
Problem: I'm very new to socket programming and working with Github projects. I tried following the simplistic approach mentioned on the project but ran into build errors with Eclipse, specifically relating to Archiving issues with WebSocket.jar and json-org.jar.
Unable to solve this, I tried importing the project into Android Studio when I ran into a whole different bug, which I'm very unfamiliar with.
I just want to make sure I'm working with this project right in the first place. This is what my client class looks like:
package com.example.culami;
import io.socket.IOAcknowledge;
import io.socket.IOCallback;
import io.socket.SocketIO;
import io.socket.SocketIOException;
import org.json.JSONException;
import org.json.JSONObject;
public class AcknowledgeExample implements IOCallback {
private SocketIO socket;
/**
* #param args
*/
/*public static void main(String[] args) {
try {
new AcknowledgeExample();
} catch (Exception e) {
e.printStackTrace();
}
}*/
public AcknowledgeExample() throws Exception
{
socket = new SocketIO();
socket.connect("http://192.168.0.108:3000/", this);
// Sends a string to the server.
socket.send("Hello Server");
// Sends a JSON object to the server.
socket.send(new JSONObject().put("key", "value").put("key2",
"another value"));
// Emits an event to the server.
socket.emit("event", "argument1", "argument2", 13.37);
}
#Override
public void onMessage(JSONObject json, IOAcknowledge ack) {
try {
System.out.println("Server said:" + json.toString(2));
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onMessage(String data, IOAcknowledge ack) {
System.out.println("Server said: " + data);
}
#Override
public void onError(SocketIOException socketIOException) {
System.out.println("an Error occured");
socketIOException.printStackTrace();
}
#Override
public void onDisconnect() {
System.out.println("Connection terminated.");
}
#Override
public void onConnect() {
System.out.println("Connection established");
}
#Override
public void on(String event, IOAcknowledge ack, Object... args) {
System.out.println("Server triggered event '" + event + "'");
}
}
I imported the socketio.jar and even WebSocket.jar and json-org.jar because it seemed these were needed as well. Any feedback on what I'm doing wrong or how I should incorporate this library in my android project will be highly appreciated since I've already spent countless hours trying to debug the build issue.
Note: I'm using Android L, API 21 and jdk1.7 to run this project.
Instead you can add
socket.io-client-0.1.0.jar
The link for his http://mvnrepository.com/artifact/com.github.nkzawa/socket.io-client/0.1.0

KryoNet: Client disconnects immediately after connecting

This seems to be a popular problem, but I'm still having trouble finding a solution even after spending a lot of time troubleshooting. I'm hoping there's an updated solution.
I'm setting up a simple Server and Client with the KryoNet Java networking library. My problem is that my client disconnects immediately after connecting to the server.
Here is my code:
Server
public class TheServer extends Listener {
static Server server;
static final int PORT = 8215;
public static void main(String[] args) throws IOException {
server = new Server();
server.start();
server.bind(PORT);
server.addListener(new TheServer());
System.out.println("server started on " + PORT);
}
public void connected(Connection c) {
System.out.println("connected: " + c.getID());
}
public void disconnected(Connection c) {
System.out.println("disconnected: " + c.getID());
}
}
Client
public class TheClient extends Listener {
static Client client;
static final String IP = "localhost";
static final int PORT = 8215;
public static void main(String[] args) throws IOException {
client = new Client();
client.start();
client.connect(5000, IP, PORT);
client.addListener(new TheClient());
//client.setKeepAliveTCP(2000);
}
}
After running TheServer and then TheClient, my console prints:
server started on 8215
connected: 1
disconnected: 1
Note that the time between the connection and disconnection is almost immediate, certainly less than the connection timeout time I set. Also note that I commented out the setKeepAliveTCP() method because while I do not think it is necessary, I inserted it to see if it would work.
After some more digging around, I found that starting the client with:
new Thread(client).start()
instead of
client.start()
fixes the problem.
"Starting with r122, client update threads were made into daemon threads, causing the child processes to close as soon as they finish initializing."

RMI cannot connect to remote server

I've been plying with RMI recently and while I managed to make it work on locahost I've been having all sorts of problem when trying to use a remote server. Here's the basic code I'm trying to run:
Server:
public class RmiServer extends UnicastRemoteObject implements RmiServerIntf {
public static final String MESSAGE = "Hello world";
public RmiServer() throws RemoteException {
}
public String getMessage() {
return MESSAGE;
}
public static void main(String args[]) {
System.out.println("RMI server started");
if (System.getSecurityManager() == null) {
System.setSecurityManager(new RMISecurityManager());
System.out.println("Security manager installed.");
} else {
System.out.println("Security manager already exists.");
}
try {
LocateRegistry.createRegistry(1099);
System.out.println("java RMI registry created.");
} catch (RemoteException e) {
e.printStackTrace();
}
try {
RmiServer obj = new RmiServer();
Naming.rebind("rmi://localhost/RmiServer", obj);
System.out.println("PeerServer bound in registry");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Remote class interface:
public interface RmiServerIntf extends Remote {
public String getMessage() throws RemoteException;
}
Client:
public class RmiClient {
RmiServerIntf obj = null;
public String getMessage() {
try {
obj = (RmiServerIntf)Naming.lookup("rmi://54.229.66.xxx/RmiServer");
return obj.getMessage();
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
}
}
public static void main(String args[]) {
if (System.getSecurityManager() == null) {
System.setSecurityManager(new RMISecurityManager());
}
RmiClient cli = new RmiClient();
System.out.println(cli.getMessage());
}
}
rmi.policy file:
grant {
permission java.security.AllPermission;
};
I compiled the classes and created a stub for the server. Then I placed client, stub, interface and policy on my machine and server, stub, interface and policy on the remote machine. The remote server being a Linux machine I made all the files executable. I also added a rule on the local firewall allowing port 1099, and opened all ports on the remote machine
After this I navigated to the server's directory on the remote machine and inserted the following command:
java -Djava.security.policy=rmi.policy RmiServer
This didn't give me problems so I went back to the local machine and entered
java -Djava.security.policy=rmi.policy RmiClient
I wait, and wait and I get the error message:
Connection refused to host: 172.31.xx.xx; nested exception is: java.net.ConnectException: Connection timed out: connect
I've been fighting with these connection errors all day yesterday and this is as far as I got. I'm sure there's only one very small thing I'm still doing wrong but I just can't find what it is.
This may not solve your problem, but I've had similar issues with JPPF (via Java RMI) on Linux. The solution was to ensure that the ephemeral port range on the Client-side machine covered only ports that were allowable by the Client-side's local firewall. E.g., if your firewall allows ports 48000 to 64000 to be connected to by an external machine, ensure that your ephemeral port range also falls within 48000 to 64000. Give that a try and let us know what happens.
System.setProperty("java.rmi.server.hostname","10.0.3.73");
Please use the above statements in your RMIServer side code, and try and connect from remote client again. It worked for me

Categories