ive got the following code as kind of a hello world test for restlet
public static void main(String[] args) throws Exception {
//Find a way to get these from the ARGS...
Settings.setCurrent(new Settings());
// Create a new Restlet component and add a HTTP server connector to it
component.getServers().add(Protocol.HTTP, 8182);
component.getContext().getParameters().add("maxThreads", "512");
component.getContext().getParameters().add("minThreads", "100");
component.getDefaultHost().attach("/findMissingPackages", Jeblet.class);
// Now, let's start the component!
// Note that the HTTP server connector is also automatically started.
component.start();
}
#Get
public String toString() {
try {
Thread.sleep(10000);
}
catch(Exception ex) { }
String settingString = "stuff";
return settingString;
}
The problem I'm having is if I open two tabs in chrome and access the server twice in a row it takes 20 seconds to get a response on the second tab. This should take 10 seconds for both tabs.
when I debug I only have one dispatcher. how do I tell restlet that I would like more than one thread?
Opening a new browser tab (or window) is not the same as opening a new connection. Browsers are really good at re-using already open connections and the 20 seconds delay is evidence of that. You can verify this by printing out the remote IP + port in your server, it will be the same for both requests.
In Firefox you can force a new connection by pressing ctrl+F5, Chrome probably has a similar feature. But you could also write a little (multi-threaded) client program that does the get-request: it is not that difficult to write and will come in handy when you need to test/debug other features of your server.
Related
I am creating a simple learning project (chat using sockets) in Java and today I faced a problem. Maybe the point is an obvious one for somebody, but I am confused with it
The purpose
To get to know (at least one of the following):
A list of the currently opened free/taken ports on a PC
Whether the port I want to use is locked
What I tried
I've created a simple raw-project and run two ServerSocket on one port. In this case I have caught a java.net.BindException with notification that "...Address already in use: JVM_Bind...". But in this way I am able to check the port avaliability only if my JVM has captured it. In case if other program listens to the port, I do not know anything about it. I am adding a code below.
public class Main {
public static void main(String[] args) throws IOException {
MyThread myThread = new MyThread();
ServerSocket serverSocket = new ServerSocket(5940);
myThread.start();
serverSocket.accept();
}
}
public class MyThread extends Thread {
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(5940);// exception is thrown here
serverSocket.accept();
} catch (IOException e) {
System.err.println("SECOND SERVER");
e.printStackTrace();
interrupt();
}
}
}
PS Any advice is warmly welcomed
I've created a simple raw-project and run two ServerSocket on one
port. In this case I have caught a java.net.BindException with
notification that "...Address already in use: JVM_Bind...". But in
this way I am able to check the port avaliability only if my JVM has
captured it. In case if other program listens to the port, I do not
know anything about it.
I think you're misinterpreting your result. I have every reason to believe that if the port you request is already bound by any process then your attempt to bind it will fail with a BindException. That takes care of
Whether the port I want to use is locked
. As for
A list of the currently opened free/taken ports on a PC
, there are system utilities that can get you that information, but it is useless to you. Whichever end initiates the connection (i.e. the client) needs to know in advance what port to try to connect to. It cannot get that from the server, because that presents a chicken & egg problem.
The usual approach is that the server listens to a specific port chosen by its developer or its admin, and that port number is provided to clients out of band -- often simply by it being a standard, well-known port number. That's how most of the basic network protocols work; for example, HTTP servers run on port 80 by default. If the wanted port happens to be unavailable when the server attempts to bind to it then that indicates a misconfiguration of the machine, and the server simply fails to start.
The client, on the other hand, does not need to choose a port number at all. The system will choose one for it automatically when it attempts to connect to the server.
I'm working on a websocket implementation that collects data from several (around 10) android clients.
So I have created a classic ServerEndpoint running currently on localhost and on client side an app that opens up a connection to the ServerEndpoint and sends sensor data every 500ms.
The whole thing works fine and on time if I use just one client.
However if I use multiple clients, they send their messages all on time, but the ServerEndpoints onMessage is called at random times. It looks like it "queues" messages from a clients for several seconds, and then fires the onMessage method 5 times in a row. I would need it always on the exact time however. Can I force this?
No errors or exceptions showing up.
This is the very basic server side:
#ServerEndpoint("/ServerEndpoint")
public class ServerEndpoint {
static Set<Session> connections = Collections.synchronizedSet(new HashSet<Session>());
#OnOpen
public void handleOpen(Session userSession){
log("opened session: "+ userSession);
connections.add(userSession);
}
#OnMessage
public void handleMessage(String message, Session userSession) throws IOException{
String userName = (String) userSession.getUserProperties().get("username");
log("received message from: "+ userName+": "+Calendar.getInstance().get(Calendar.SECOND)+":"+Calendar.getInstance().get(Calendar.MILLISECOND)+ " "+ message );
....
}
#OnClose
public void handleClose(Session userSession){
log("closed session: "+userSession);
connections.remove(userSession);
}
I guess I miss some configuration option of the ServerEndpoint or something. Does someone know what causes this behavior and how to solve it?
Alright got it. The issue was Tomcat 7 which has obviously some issues with websockets. Using Tomcat 8, it works now without any queues or big delay. Also other minor errors and connection problems were solved by the update and it seems to be much more stable.
Maybe this helps someone facing similar problems.
To convince some people to switch from old school tech, I need to build a chat demo application that manages more than 10K concurrent connections using Java (like Node.Js stuff).
I have tested Netty 5.0 which is awesome but requires lot of work to be done; on the other hand Jetty 9.3 is great but is slow compared to other competitors.
After some search I found the Vert.x 3 toolkit which is based on Netty with a plethora of great tools (no need to reinvent the wheel), I have seen the examples in git and I was able to build a websocket server, etc.
public void start() throws Exception {
vertx.createHttpServer().websocketHandler(new Handler<ServerWebSocket>() {
#Override
public void handle(ServerWebSocket e) {
// business stuff in the old style not yet lambda
}
}).listen(port);
}
Being new to the Vert.x world, I could not figure out how to manage connected users using it, normally the old fashion way is to use something like:
HashMap<UUID,ServerWebSocket> connectedUsers;
When a connection is established I check if it exists; if not I add it as a new entry and do some functions to send, broadcast, retrieve through the collection and so on.
My question is does Vert.x 3 have something to deal with connections to track them and remove those who left (ping pong), broadcast, etc. or should I implement them from scratch using cookies, session, ....)
I could not find any real example using Vert.x 3.
Basically, the scope of the websocketHandler represents a connection. In your example this is your anonymous class. I created a little websocket chat example where I use the Vert.x event bus to distribute the messages to all the clients.
In the start method of the server we handle the websocket connections. You can implement the closeHandler to monitor client disconnection. There are also handlers for exceptions, ping-pong, etc. You can identify a specific connection by using the textHandlerID, but you have also access to the remote address.
public void start() throws Exception {
vertx.createHttpServer().websocketHandler(handler -> {
System.out.println("client connected: "+handler.textHandlerID());
vertx.eventBus().consumer(CHAT_CHANNEL, message -> {
handler.writeTextMessage((String)message.body());
});
handler.textMessageHandler(message -> {
vertx.eventBus().publish(CHAT_CHANNEL,message);
});
handler.closeHandler(message ->{
System.out.println("client disconnected "+handler.textHandlerID());
});
}).listen(8080);
}
The client example is also written in Java. It just prints all the received messages on the websocket connection to the console. After connection it sends a message.
public void start() throws Exception {
HttpClient client = vertx.createHttpClient();
client.websocket(8080, "localhost", "", websocket -> {
websocket.handler(data -> System.out.println(data.toString("ISO-8859-1")));
websocket.writeTextMessage(NAME+ ":hello from client");
});
}
In web application, i have a chat gadget embedded in web page (.HTML). The back end code of my application Java and the chat gadget communicates with .PHP. I do not have access to .PHP environment.
I can only code in java to handle HTML requests using Java.
Issue:
When i click refresh on browser, the new chat session begins every time.
Even when i jump from one page to other the chat session refreshes and new chat begins.
I am not suppose to do any changes in .PHP environment but need to change code in Java
Question:
I want to mold program in such a way that .PHP environment
thinks that page has not been refreshed and does not break the session.
I think proxy might be solution but how to implement those? Any other solution for same.
To build a proxy, first create a ServerSocket on a port that the widget will talk to, then start accept accepting connection on it.
As new connections come in, create a new Socket to the php server. Then you have to pipe the input from one to the output of the other and vice-versa.
That's a generic proxy. For your case you'd have to add some logic to detect that a connection already exists (probably with a cookie), then reuse the existing socket instead of creating a new.
Unfortunately, it will be a bit of work to parse the input, and get the protocol to match what php is doing.
(edit to add example)
Here's a barebones generic proxy example to get you started. Run this then point your browser to localhost.
public class Proxy {
public static void main(String args[]) throws Exception {
ServerSocket server = new ServerSocket(80);
Socket browser = server.accept();
Socket remote = new Socket("google.com", 80);
pipe(browser.getInputStream(), remote.getOutputStream());
pipe(remote.getInputStream(), browser.getOutputStream());
remote.close();
server.close();
}
private static void pipe(InputStream in, OutputStream out) throws IOException {
while(in.available() == 0) {
Thread.yield();
}
while(in.available() > 0) {
int data = in.read();
System.out.write(data);
out.write(data);
}
}
}
A working solution would need to be multithreaded (or async) and instead of just piping the data between servers you'll have to get in there and inspect it, then decide if you need to open a new socket or re-use an existing one.
Let me explain the problem by a scenario :
1) User visit my page "www.proxy4html.com" , fills up the form:
web-address: |www.google.co.in |
2) click submit.
3) Gets google home page with "www.proxy4html.com" in browser address bar.
Now to fetch the contents from web I am using java.net.HttpURLConnection (although to resolve this I have tried several other options too). The code works as expected if it runs stand alone
(i.e while running through public static void main(String..).. thread, it fetched whatever the html is on given web address).
But the same when runs under the Servlet environment it throws
java.net.ConnectException: Connection timed out: connect
Here is the code:
public void write(String urlString, PrintWriter writer) {
URL url;
try {
url = new URL(urlString);
HttpURLConnection huc = (HttpURLConnection) url.openConnection();
HttpURLConnection.setFollowRedirects(false);
huc.setConnectTimeout(15 * 1000 * 60);
huc.setReadTimeout(15 * 1000 * 60);
huc.setRequestMethod("GET");
huc.connect();
InputStream input = url.openStream();
logger.info("got input stream");//I never reach here in servlet env :(
int i = 0;
while((i = input.read()) != -1) {
writer.write(i);
System.out.print((char)i);
}
input.close();
} catch (ConnectException e) {
logger.log(Level.SEVERE, "", e);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
The code example given may not appear clean but point to be taken is that when the above method is invoked from Servlet passing a proper URL (and whatever outputstream), the connection is never made.
I am running all this on my tomcat which is on my local machine, which is in some corporate network (you may not want get any conclusion concerning firewall because same code is running under a p.s.v.main).
please help....
Thanks in advance.
Edit: I tried somewhat same at home and it worked fine as expected. I guess this question falls more into operation system domain rather than java. So I will like to rephrase my question again:
Is operating system (Window 7) is somehow preventing tomcat to make Http requests?
Is their any configuration under Window 7 that doesn't allow application to make Http Request other than browser?
I have seen in times that Mozilla Firefox (which I am running from a directory which is copied instead of being installed i.e may not have admin privileges and doesn't have a window registry) never able to do regular update to itself.
I understand that you prefer to insist that this is not a firewall issue (as the same code runs well as a standalone Java program), but I'm willing to take a risk here.
If you're absolutely sure that the very same code is being run in both cases (standalone case, and Tomcat case), there still is a possibility that it's a firewall issue.
The built-in firewall in Windows 7 assigns outbound rules per process per port. Is it possible that your standalone program runs with a JVM that has been allowed outbound access, whereas your Tomcat server runs with a JVM that hasn't been allowed outbound access?
In other words, are you absolutely confident that your standalone program, and your Tomcat server, are being run by the very same JVM? Very same java.exe? Under Windows, it's possible that your standalone program is actually being run by javaw.exe.
(You didn't mention whether you tried to completely disable the firewall. If you can disable the firewall completely, I'd suggest you do so, for the purpose of troubleshooting)