Java websocket draft refuses handshake - java

I am working on android(Java) using TooTallNate's java websockets from this tutorial to consume websockets on android to connect with ws:// but I am getting error draft org.java_websocket.drafts.Draft_10#4560b1d0 refuses handshake. I tried their other draft versions but none of them worked either.

First of all, you want to use the Draft_6455, it is the current spec, the rest may or may not work on different servers reliably. There are constructors for the draft object which take a List<IProtocol>. If no protocol specified matches one offered by the server, the handshake will be refused.
public Draft_6455( List<IExtension> inputExtensions , List<IProtocol> inputProtocols )
public Draft_6455( List<IExtension> inputExtensions , List<IProtocol> inputProtocols, int inputMaxFrameSize )
I ran into a similar issue to yours with the newest version of TooTallNate's Java Websockets, my code was like so:
knownExtensions = new java.util.ArrayList();
knownProtocols = new java.util.ArrayList();
if(this._protocol){
knownProtocols.add(new org.java_websocket.protocols.Protocol(this._protocol));
}
this._socket = new _WebSocket(uri, new org.java_websocket.drafts.Draft_6455(knownExtensions, knownProtocols), toHashMap(this._headers), this._timeout);
You MUST have at least one valid protocol (even if it is a empty string), or you get the above error you referenced. So I changed my code to be:
...
if(this._protocol){
knownProtocols.add(new org.java_websocket.protocols.Protocol(this._protocol));
}
/* -=-=-=- NEW ADDED CODE -=-=-=- */
else {
knownProtocols.add(new org.java_websocket.protocols.Protocol(""));
}
/* -=-=-=- END NEW ADDED CODE -=-=-=- */
...
This is what broke, no protocol specified caused the "refuses handshake" error message for me.
Please note there are a couple of reasons for the above "refuses handshake", but in my case it was the missing empty protocol...

Did you try this on broswer? You will get a err code on the broswer.
You can write a simple js file to start and test whether this problem is on the server or is on the app.
Here is a demo,it won't take you too much time.
<script type="text/javascript">
function send() {
var url = 'ws://192.168.1.101:8080/WebSocket/echo';
var vs = new WebSocket(url);
vs.onopen = function(evt){
vs.send(te.value)
};
vs.onmessage = function(evt){
alert(evt.data);
};
}

Basically if you have for example a protocol "my-protocol"
ArrayList<IProtocol> protocols = new ArrayList<IProtocol>();
protocols.add(new Protocol("my-protocol"));
//Uncomment below if you want to have a fallback
//protocols.add(new Protocol(""));
Draft_6455 my_draft = new Draft_6455(Collections.<IExtension>emptyList(), protocols);
Taken from here

Related

Is it possible to write text into a web page after it has loaded?

Let me get straight to an example to explain further.
final var socket = new java.net.ServerSocket(1234);
for (;;)
{
try (final var client = socket.accept())
{
client.getOutputStream().write("HTTP/1.1 200 OK\r\n\r\n".concat(java.time.Instant.now().toString()).getBytes());
}
}
When I now open my browser of choice (Firefox cough) I'll receive the current time and date. The question now is how I can write to that socket at a later point in time.
hypothetical solution
Here's something I already tried, but doesn't work at all.
final var socket = new java.net.ServerSocket(1234);
for (;;)
{
try (final var client = socket.accept())
{
client.getOutputStream().write("HTTP/1.1 200 OK\r\n\r\n".concat(java.time.Instant.now().toString()).getBytes());
client.getOutputStream().flush();
Thread.sleep(1000L);
client.getOutputStream().write("And another paragraph.".getBytes());
}
}
The result is a web page loading for approximately a single second, printing out the following result (may vary due to different date and time on your end).
2019-01-19T18:19:15.607192500Z
And another paragraph.
Instead I would like the see something like that:
print out the current time and date.
wait a second without the content of the web page changing.
print out the next paragraph.
How would I go about implementing that?
Is it possible for the server to write text into a web page after it is loaded? Yes it definitely is, but these days I suspect it it is rarely done. I started web development in the 1990s and back then that was a pretty common technique. We used it to write live chat messages to browsers with no Javascript. These days Javascript is ubiquitous and powerful, so using client-side Javascript to update a page will be the best option in most cases.
That said, the technologies we used for writing server-side updates back then should still work now. I suspect the reason you don't see updates in your browser is because it doesn't know it should start displaying the page before everything is loaded. Using chunked transfer encoding, a 1990s technology still supported by modern browsers, should resolve that. It it allows the server to indicate when a 'chunk' of data is complete and browsers will generally process each chunk immediately rather than wait for all the chunks to arrive.
The easiest way to use chunked transfer encoding is to use an HTTP library like Apache HttpComponents, then wrap your output stream in the appropriate class:
final var socket = new java.net.ServerSocket(1234);
for (;;)
{
try (final var client = socket.accept())
{
var outputStream = new ChunkedOutputStream(client.getOutputStream());
outputStream.write("HTTP/1.1 200 OK\r\n\r\n".concat(java.time.Instant.now().toString()).getBytes());
outputStream.flush();
Thread.sleep(1000L);
outputStream.write("And another paragraph.".getBytes());
}
}

Vertx.io GET silently fails

I'm writing a POC using vertx, looking for alternatives when we have to migrate Spring Web from 4.x to 5 to be java 9 compliant.
I've written a simple client, just a GET towards a publicly available server just to get something working but it silently fails me.
public List<String> pull() {
Vertx vertx = Vertx.vertx();
HttpClientOptions options = new HttpClientOptions().setLogActivity(true);
HttpClient hc = vertx.createHttpClient(options);
hc.getNow(80, "http://sunet.se", "/",r -> {
System.out.println("\n****** Handler called! ***\n");
});
return new ArrayList<>();
}
This will silently fail and I cannot understand why.
As far as I can tell, I do exactly as in the examples given in the docs.
In desperation I fired up wire shark and according to WS, there is no actual call (when I use the browser WS captures that). So, it seems my call is never actually done. I don't get any exceptions or anything. Setting the log level to debug gives nothing noteworthy other than
Failed to get SOMAXCONN from sysctl and file /proc/sys/net/core/somaxconn. Default: 128
And that should not fail the call.
I've also tried using vertx.io WebClient but that fails also, in the same manner.
UPDATE
I've managed to get it to work but with a caveat.
As #tsegismont states in his answer, the protocol part of the URI shouldn't be there, that was not in the examples, I just missed it myself.
I ran my example as a stand-alone and then it worked.
My original example was run as a junit test (it's an easy way to test code and I usually try to write the test code first) and when it's run as a junit test it still doesn't work. Why that is, I have no idea. I would greatly appreciate if someone could tell me how to get that to work.
The getNow variant you use expects the server host, not a URL. It should be:
hc.getNow(80, "sunet.se", "/",r -> {
System.out.println("\n****** Handler called! ***\n");
}
If you found a snippet like this in the Vert.x docs it's a bug. Would you mind to report it?
Now a few comments.
1/ The HttpClient is a low-level client.
Most users should prefer the Vert.x Web Client
Here's an example for your use case:
WebClient client = WebClient.create(vertx);
client
.get(80, "sunet.se", "/")
.send(ar -> {
if (ar.succeeded()) {
// Obtain response
HttpResponse<Buffer> response = ar.result();
System.out.println("Received response with status code" + response.statusCode());
} else {
System.out.println("Something went wrong " + ar.cause().getMessage());
}
});
2/ Create a single Vert.x and WebClient instance
Do not create a Vert.x and WebClient instance on every method call.
It wastes resources and is inefficient.

Run out of ports calling my webservice from an android app

I have an android app and a C# web service
I am hosting my web service on IIS Express - nothing fancy just set up the directories.
My android app go to the web service gets the data and then displays it on the screen and repeats this as fast as it can go.
After a while my android app will throw the following exception:
"SoapFault - faultcode: 'soap:Server' faultstring: 'Server was unable to process request. ---> No ports available in the range 10101 to 11100' faultactor: 'null' detail: org.kxml2.kdom.Node#41bdf340"
I have Googled around a bit and have not found anything that will help me.
I ran CurrPorts to watch the ports and it looks like every time the app calls the web service it is using a different port.
They all use port 80 but different remote ports.
The exception is being thrown on the following line of code
"SoapPrimitive response = (SoapPrimitive) _envelope.getResponse();"
If I run IISReset the app will go back to getting data again until sometime thereafter to get the exception mentioned above.
Here is the code for my web service which is just returning a comma separated string (it will do something more interesting just trying to get this working)
Web service code
[WebMethod]
public string GetDefaultResults()
{
return "100,1,0,125.987,124.993,117.904,116.038";
}
Here is the code that my android app uses to call the web service.
I create a new thread and have it call this method then get the string value split it on ',' then put it in a few different TextViews
public class WebService implements Runnable{
private static String NAMESPACE = "http://tempuri.org/";
private static String URL = "http://mymachine/mywebservice/service.asmx";
private static String SOAP_ACTION = "http://tempuri.org/";
private String _soapAndMethod;
private HttpTransportSE _androidHttpTransport;
private SoapSerializationEnvelope _envelope;
private String _methodName;
public WebService(String methodName) {
_methodName = methodName;
_soapAndMethod = SOAP_ACTION + _methodName;
SoapObject request = new SoapObject(NAMESPACE, methodName);
_envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
_envelope.dotNet = true;
_envelope.setOutputSoapObject(request);
_androidHttpTransport = new HttpTransportSE(URL);
}
#Override
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
}
public String InvokeWebService() {
String resTxt = null;
try {
_androidHttpTransport.call(_soapAndMethod, _envelope);
SoapPrimitive response = (SoapPrimitive) _envelope.getResponse();
resTxt = response.toString();
} catch (Exception e){
e.printStackTrace();
}
return resTxt;
}
}
Any help would be great. Thank you to those who do respond. Is there some setting in IIS I need to change? Is there something I missed in my code?
Additional information:
When the server is responding the webservice request IIS creates a process called w3wp.exe and it this process that is running out of ports.
Doing in a little digging and experimentation the Webservice gets newed up each call to "GetDefaultResults". Which leaves w3wp.exe in a Listening state and they never go away until the iisreset is run.
Some time later it uses the remaining ports available and starts throwing that exception.
Why is it not reusing the same webservice instead of creating a new one each time.
If that is not possible what code do I write in the Webservice to close the connection after it is finished. I put in a hack to cause it close after 5 seconds to see if that would work at least.
It does clean up w3wp.exe but after a short time I start getting this exception on the client.
"expected: START_TAG {http://schemas.xmlsoap.org/soap/envelope/}Envelope (position:START_TAG #2:7 in java.io.InputStreamReader#41beb098) "
so this is not a work around but it helped me understand what the problem is a little better.
protected override void Dispose(bool disposing)
{
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 5000;
timer.Elapsed += timer_Elapsed;
timer.Start();
base.Dispose(disposing);
}
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Environment.Exit(1);
}
Thanks for your help.
If you failed your first request, you might need to enable IIS Express to allow external connections. In your case, it looks like it only failed after running for a while.
In your question, I see that you
"go to the web service gets the data and then displays it on the screen and repeats this as fast as it can go.
did not call "close" on HttpTransportSE
You might be running out of local ports. Are you reusing the connection on all your requests? If not, try to close it when you are done.
My Webservice was referencing an api to get the values from then pass them over a webservice to the android app.
The problem was that every time the webservice was being called a new reference would be created to the api and after the request was sent it would never close out the port. As soon as I stopped referencing the api everything worked.
A cludge to get this to work is I had the webservice monitor a folder and send the data in the file that was last created. Then created another program to attach to the api and output the data to that folder. Not the most elegant solution but it works as a proof of concept for what I am doing.
Still not entirely sure why the Webservice was never closing the port and I am suspect that the Webservice could not dispose of the reference to the api but I am not really sure.

MATLAB proxy could not be created in 180000 milliseconds

I am using the matlabcontrol-4.0.0.jar library to call Matlab from Java. This on Ubuntu 11.10, Matlab r2011b and Java version "1.6.0_23".
When trying to run this simple program:
public static void main(String[] args) throws MatlabConnectionException,
MatlabInvocationException {
//Create a proxy, which we will use to control MATLAB
MatlabProxyFactory factory = new MatlabProxyFactory(options);
MatlabProxy proxy = factory.getProxy();
//Display 'hello world' just like when using the demo
proxy.eval("disp('hello world')");
//Disconnect the proxy from MATLAB
proxy.disconnect();
}
I get, after the Matlab launch screen appears (which is good), a time out:
Exception in thread "main" matlabcontrol.MatlabConnectionException:
MATLAB proxy could not be created in 180000 milliseconds at matlabcontrol.RemoteMatlabProxyFactory.getProxy(RemoteMatlabProxyFactory.java:158)
at
matlabcontrol.MatlabProxyFactory.getProxy(MatlabProxyFactory.java:81)
at Main.main(Main.java:15)
I've looked everywhere including all the tips from provided by stackoverflow, but nothing seems to fit the problem i am encountering
*UPDATE*
I forbore to mention that I already tried the scenario described by Joshua Kaplan (thanks!) .This seems be for my case of no help, meaning that it just keeps waiting. Could someone perhaps elaborate on the communication protocol between java and the matlab proxy?
-> It could be an incompatibility issue as well, I've posted on the website delivering the resource, have received no answer so far...
*END UPDATE*
So, any of you a tip where to start looking, that would be wonderful
thanks
The getProxy() method is a blocking operation with a default timeout of 3 minutes (or 180 seconds or 180000 milliseconds). For most people's machines that is long enough, if the connection was not established in that amount of time then something has gone wrong. However, this timeout can be changed by creating an instance of a MatlabProxyFactoryOptions which is done by using a MatlabProxyFactoryOptions.Builder. The MatlabProxyFactoryOptions instance you create is passed into MatlabProxyFactory's constructor. Here's an example with a 5 minute timeout:
MatlabProxyFactoryOptions options = new MatlabProxyFactoryOptions.Builder()
.setProxyTimeout(300000L)
.build();
MatlabProxyFactory factory = new MatlabProxyFactory(options);
MatlabProxy proxy = factory.getProxy();
Alternatively you can request a proxy which is a non-blocking operation that has no timeout. Once the proxy has been created it will be passed to the provided callback. Example:
MatlabProxyFactory factory = new MatlabProxyFactory();
factory.requestProxy(new MatlabProxyFactory.RequestCallback()
{
public void proxyCreated(MatlabProxy proxy)
{
//TODO: Make use of the proxy
}
});
I got similar problem. Main issue is that in your imported .jar file "matlabcontrol-4.0.0.jar" there is default, configuration in class Configuration.java. In my case there was problem, that libraries cannot properly call matlab with all arguments. Try to add to your project not .jar file, but package matalbcontrol with all source .java files. You can download it form the same page http://code.google.com/p/matlabcontrol/downloads/list, form where you got .jar libs. Then in Configuration.java edit getMatlabLocation() lines:
else if(isWindows() || isLinux())
{
matlabLoc = "matlab";
}
replace with:
else if(isLinux())
{
matlabLoc = "/usr/local/MATLAB/R2011b/bin/matlab"; //or place where you got installed your matlab, directory bin, in my case, like in example
}
else if(isWindows())
{
matlabLoc = "matlab";
}

GAE/J Channel API exception even though messages go through?

I open a channel during the app initialization through a series of ajax calls:
getToken = function () {
xhr = new XMLHttpRequest();
xhr.open("GET", "/game?action=getChannelToken", true);
xhr.send(null);
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status==200) {
connect(xhr.responseText);
}
};
};
Servlet:
ChannelService channelService = ChannelServiceFactory.getChannelService();
channelToken = channelService.createChannel(uid);
The token is then returned to the javascript for:
connect = function (token) {
// alert ("connect");
var channel = new goog.appengine.Channel(token);
var socket = channel.open();
socket.onopen = onOpened;
socket.onmessage = onMessage;
socket.onerror = onError;
socket.onclose = onClose;
};
I'm getting this error:
WARNING: /_ah/channel/dev
com.google.appengine.api.channel.dev.LocalChannelFailureException:
Channel for application key null not
found.
The channel creation part is very simple, so I do not understand where is the problem.
System.out.println (channelToken); returns something like
channel--rrmk8i-100002139544068
(100002139544068 is the uid I used to create the channel), so it seems to return a real token. Moreover, channelService.sendMessage(msg); (using the same uid as before), sends the message without any problem.
Does anyone have any idea why this is happening?
I'm using eclipse 3.5.2, GAE/J 1.4.2 and ubuntu 10.10
Googling for that exception I found only one discussion here:
http://groups.google.com/group/google-appengine-java/browse_thread/thread/19f250b1ff0e4342
but changing var channel = new goog.appengine.Channel(token); to var channel = new goog.appengine.Channel(uid); did not solve anything (and, from what I understand, it shouldn't)
I can think of two reasons this could be happening:
You're restarting the dev_appserver.py while your client is still running. Because the client will be polling with an "old" token that the dev_appserver doesn't know about, it will throw this error. If this is the case, just refresh your client page after restarting the dev_appserver (or otherwise force it to request a new token).
connect() is being called with an invalid token. It sounds like you've ruled that out but if the above isn't true it might be worth double-checking.
You can see what token the client is polling with you can open up Firebug or the Chrome dev console and look for requests to a path like this:
http://localhost:8080/_ah/channel/dev?command=poll&channel=channel-1503856530-alpha-token&client=1
The channel-1503856530-alpha-token part of that URL is the token passed to "new goog.appengine.Channel()".

Categories