WebSocket Javascript client not receiving messages from server - javascript

I've got a Java web application deployed on a local GlassFish 4.1 server that implements WebSockets to inter-operate with the web client. I'm able to successfully execute client-to-server communication over the socket, but server-to-client communication doesn't work for some reason.
The Java code that sends messages to the client:
try
{
String msg = ServerClientInteropManager.toResponseJSON(response);
parentSession.getBasicRemote().sendText(msg);
FLAIRLogger.get().info("Sent response to client. Message: " + msg);
}
catch (IOException ex) {
FLAIRLogger.get().error("Couldn't send message to session " + parentSession.getid() + ". Exception - " + ex.getMessage());
}
The Javascript code:
pipeline_internal_onMessage = function(event)
{
var msg = JSON.parse(event.data);
console.log("Received message from server. Data: " + event.data);
};
function pipeline_init()
{
if (PIPELINE !== null || PIPELINE_CONNECTED === true)
{
console.log("Pipline already initialized");
return false;
}
else
{
var pipelineURI = "ws://" + document.location.host + document.location.pathname + "webranker";
console.log("Attempting to establish connection with WebSocket # " + pipelineURI);
if ('WebSocket' in window)
PIPELINE = new WebSocket(pipelineURI);
else if ('MozWebSocket' in window)
PIPELINE = new MozWebSocket(pipelineURI);
else
{
console.log("FATAL: No WebSockets support");
alert("This browser does not support WebSockets. Please upgrade to a newer version or switch to a browser that supports WebSockets.");
return false;
}
// the other event listeners get added here
PIPELINE.onMessage = pipeline_internal_onMessage;
PIPELINE_CONNECTED = true;
window.onbeforeunload = function() {
pipeline_deinit();
};
console.log("Pipeline initialized");
return true;
}
}
The onMessage function is never fired, even when the server successfully calls the sendText() method. Using the AsyncRemote yields the same results. The onError listeners on both ends don't report anything either. This is my first time working with sockets so I might be missing something elementary.

replace
PIPELINE.onMessage = pipeline_internal_onMessage
with
PIPELINE.onmessage = pipeline_internal_onMessage
Please refer here for more.

Related

javascript websockets error

I Have a simple setup witH a pytHon server running on a raspberry PI inside my Home network. On my PC I Have a basic HTML page witH some Javascript tHat sHould communicate witH tHe py server on my raspberry pi. THe server on tHe raspberry pi works perfect wHen tested from telnet on my PC.
Here is tHe PytHon code:
import socket
from time import*
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = ""
port = 51025
s.bind((host, port))
s.listen(1)
conn, addr = s.accept()
print "Connection open"
print conn, addr
while 1:
data = conn.recv(4096)
if data:
print "msg received"
conn.sendall(data +" 12 uniflu")
else:
print "connection lost"
s.listen(1)
conn, addr = s.accept()
print "Connection open"
print conn, addr
This is the javascript code:
window.onload = function() {
// Get references to elements on the page.
var form = document.getElementById('message-form');
var messageField = document.getElementById('message');
var messagesList = document.getElementById('messages');
var socketStatus = document.getElementById('status');
var closeBtn = document.getElementById('close');
var openBtn = document.getElementById('open');
// The rest of the code in this tutorial will go here...
// Create a new WebSocket.
var socket = new WebSocket('ws://192.168.0.81:51025');
// Close the WebSocket connection when the close button is clicked.
// Show a connected message when the WebSocket is opened.
socket.onopen = function(event) {
socketStatus.innerHTML = 'Connected to: ' + event.currentTarget.URL;
socketStatus.className = 'open';
};
// Handle any errors that occur.
socket.onerror = function(error) {
console.log('WebSocket Error: ' + error);
};
// Close the WebSocket connection when the close button is clicked.
closeBtn.onclick = function(e) {
e.preventDefault();
// Close the WebSocket.
socket.close();
return false;
};
// Show a disconnected message when the WebSocket is closed.
socket.onclose = function (event) {
var reason;
alert(event.code);
// See http://tools.ietf.org/html/rfc6455#section-7.4.1
if (event.code == 1000)
console.log( "Normal closure, meaning that the purpose for which the connection was established has been fulfilled.");
else if(event.code == 1001)
console.log("An endpoint is \"going away\", such as a server going down or a browser having navigated away from a page.");
else if(event.code == 1002)
console.log("An endpoint is terminating the connection due to a protocol error");
else if(event.code == 1003)
console.log("An endpoint is terminating the connection because it has received a type of data it cannot accept (e.g., an endpoint that understands only text data MAY send this if it receives a binary message).");
else if(event.code == 1004)
console.log("Reserved. The specific meaning might be defined in the future.");
else if(event.code == 1005)
console.log("No status code was actually present.");
else if(event.code == 1006)
console.log("The connection was closed abnormally, e.g., without sending or receiving a Close control frame");
else if(event.code == 1007)
console.log("An endpoint is terminating the connection because it has received data within a message that was not consistent with the type of the message (e.g., non-UTF-8 [http://tools.ietf.org/html/rfc3629] data within a text message).");
else if(event.code == 1008)
console.log("An endpoint is terminating the connection because it has received a message that \"violates its policy\". This reason is given either if there is no other sutible reason, or if there is a need to hide specific details about the policy.");
else if(event.code == 1009)
console.log("An endpoint is terminating the connection because it has received a message that is too big for it to process.");
else if(event.code == 1010) // Note that this status code is not used by the server, because it can fail the WebSocket handshake instead.
console.log("An endpoint (client) is terminating the connection because it has expected the server to negotiate one or more extension, but the server didn't return them in the response message of the WebSocket handshake. <br /> Specifically, the extensions that are needed are: " + event.reason);
else if(event.code == 1011)
console.log("A server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request.");
else if(event.code == 1015)
console.log("The connection was closed due to a failure to perform a TLS handshake (e.g., the server certificate can't be verified).");
else
console.log("Unknown reason");
$("#thingsThatHappened").html($("#thingsThatHappened").html() + "<br />" + "The connection was closed for reason: " + reason);
};
// Send a message when the form is submitted.
form.onsubmit = function(e) {
e.preventDefault();
// Retrieve the message from the textarea.
var message = messageField.value;
// Send the message through the WebSocket.
socket.send(message);
// Add the message to the messages list.
messagesList.innerHTML += '<li class="sent"><span>Sent:</span>' + message +
'</li>';
// Clear out the message field.
messageField.value = '';
return false;
};
// Handle messages sent by the server.
socket.onmessage = function(event) {
var message = event.data;
messagesList.innerHTML += '<li class="received"><span>Received:</span>' +
message + '</li>';
};
};
WHen I load tHe HTML page in my firefox browser, I can see tHe connection being made in pytHon by tHe printout, but after tHis tHe server becomes unresponsive. I also see tHe error message 1006 in tHe browser. Does anyone know tHis area and can Help me? WHy does it work very well from putty and not from tHe web browser?

Server-Sent Events with Ruby Grape

I am trying to create Server-Sent events on my Ruby Grape API.
The problem is that the connection seems to be closed really fast all the time, as I get Connection closed event all the time on test webpage.
The client connects to the server as I can see the method being called, but I would like to know why is the connection not constant and why I don't receive the data I send using the Thread.
Here is my Ruby code:
$connections = []
class EventsAPI < Sinantra::Base
def connections
$connections
end
get "/" do
content_type "text/event-stream"
stream(:keep_open) { |out|
puts "New connection"
out << "data: {}\n\n"
connections << out
}
end
post "/" do
data = "data\n\n"
connections.each { |out| out << data }
puts "sent\n"
end
end
Here is my Javascript:
var source = new EventSource('http://localhost:9292/events');
source.onmessage = function(e) {
console.log("New message: ", e.data);
showMessage(e.data);
};
source.onopen = function(e) {
// Connection was opened.
};
source.onerror = function(e) {
console.log("Source Error", e)
if (e.eventPhase == EventSource.CLOSED) {
console.log("Connection was closed");
// Connection was closed.
}
};
var showMessage = function(msg) {
var out = document.getElementById('stream');
var d = document.createElement('div')
var b = document.createElement('strong')
var now = new Date;
b.innerHTML = msg;
d.innerHTML = now.getHours() + ":" + now.getMinutes() + ":" +now.getSeconds() + " ";
d.appendChild(b);
out.appendChild(d);
};
EDIT: I got it working with the GET method (I changed the Grape::API to Sinatra::Base as Grape does not implement stream). I now receive data, but the connection is not kept alive and when I use the post method the data never reaches the browser.
Thank you in advance for your answers.
The JS code looks correct. My guess is that you should not start a new thread for your infinite loop. What will be happening is that the main thread will carry on executing, reach the end of its block, and close the http request. Your detached thread is then left writing to a non-existent out stream.
UPDATE in response to your EDIT: POST is not supported in SSE. Data can only be passed to an SSE process by using GET data or cookies.

If Websocket connection can't be established do something else

I'm currently running into a problem you guys might be able to help me with..
I'm using websockets to connect to a custom server. Now i want to integrate a second Server IP if the first one isn't available.
How is it possible to detect, that the connection couldn't be made because the server isn't reachable? When I enter a wrong ws://url in my script, Chrome for example gives me the following error:
WebSocket connection to 'wss://1234/' failed: Error in connection establishment: net::ERR_NAME_NOT_RESOLVED
in Firefox it's something complete different. Do you guys of any method to catch this error with Javascript?
Basically when the ws:// url can't be reached, i want to change a variable with a different Server-IP and try it with this one again...
Thanks for your help!
It seems there's no way to catch the problem on instantiation, even though the magical JavaScript black box somehow seems to know the problem occurs on the new WebSocket.
To detect this error, use the following:
ws = new WebSocket(server);
ws.onerror = function (evt) {
if (ws.readyState == 3) {
//Connection closed.
}
}
thanks #orbitbot,
I'm using a framework called jwebsocket (jwebsocket.org). My Code is basically this:
serverstate = "0";
console.log(serverstate);
function logon() {
if(serverstate == "0") {
lURL = "wss://testurl-one:9797";
} else if (serverstate == "1") {
lURL = "wss://testurl-two:9797";
}
var gUsername = "user";
var lPassword = "pass";
console.log( "Connecting to " + lURL + " and console.logging in as '" + gUsername + "'..." );
var lRes = lWSC.logon( lURL, gUsername, lPassword, {
// OnOpen callback
OnOpen: function( aEvent ) {
console.log( "jWebSocket connection established." );
},
// OnMessage callback
OnMessage: function( aEvent, aToken ) {
var lDate = "";
if( aToken.date_val ) {
lDate = jws.tools.ISO2Date( aToken.date_val );
}
console.log( "jWebSocket '" + aToken.type + "' token received, full message: '" + aEvent.data + "' " + lDate + "" );
console.log(aToken);
}
},
// OnClose callback
OnClose: function( aEvent ) {
console.log( "Disconnected from Server" );
console.log("Using next server..");
serverstate = "1";
console.log(serverstate);
console.log("Trying to connect to next server");
logon();
},
// OnClose callback
OnError: function( aEvent ) {
console.log ("Some error appeared");
}
});
console.log( lWSC.resultToString( lRes ) );
}
Of course this would work so far. My Problem is that im using websockets to open a connection, get some information, and after that close the connection again.
since this code will always be fired if the server connection is closed (which in many cases i want to..) i can't use it like that...
any other ideas on this problem ?
I got it.. for everyone else who's interested:
When connection is made you receive a message from there server. So if the server is not available.. there'll be no message. So i just added a variable to the "OnMessage" Part.. and in the disconnect i check if a message was received. If not the server isn't there.. if yes, everything works fine..
Assuming your code is something like this,
var host = 'ws://a.real.websocket.url';
var socket = new WebSocket(host);
... you just need to surround the call to new WebSocket with a try/catch block, something like this
try {
var socket = new WebSocket(host);
} catch (e) {
// inspect e to understand why there was an error
// and connect to another url if necessary
}
That being said, it might be easier to work with a websockets library such as Socket.IO or SockJS (https://github.com/sockjs/sockjs-client), which then would change your reconnection code logic to whatever the libraries provide.

Duplicate Events Socket.io and Node.js over STOMP

I need some help about my node.js+socket.io implementation.
This service expose a server that connects to an ActiveMQ broker over the STOMP protocol, using the stomp-js node.js module to receive events; that then are displayed in a web front end through websockets using socket.io.
So, everything was fine until I started use the Filters feature of ActiveMQ, but this was not the failure point because of my and my team researching, we found the way to ensure the implementation was fine, the problem comes with the connections: So here's the thing, I receive the filters to subscribe, I successfully subscribe to but when I receive a new set of filters is when comes the duplicated, triplicated and more and more messages depending the number of times that I subscribe-unsubscribe to.
So making some debug, I cannot see what's the problem but I'm almost sure that is some bad implementation of the callbacks or the program flow, I'll attach my code to read your comments about it.
Thanks a lot!
var sys = require('util');
var stomp = require('stomp');
var io = require('socket.io').listen(3000);
var socket = io.sockets.on('connection', function (socket) {
var stomp_args = {
port: 61616,
host: 'IP.ADDRESS',
debug: true,
};
var headers;
var client = new stomp.Stomp(stomp_args);
var setFilters = false;
socket.on('filtros', function (message) {
console.log('DEBUG: Getting filters');
if(setFilters){
client.unsubscribe(headers);
}
else{
client.connect();
}
var selector = '';
headers = '';
for(var attributename in message){
console.log(attributename+" : " + message[attributename]);
if(message[attributename] != ''){
selector += ' ' + attributename + '=\'' + message[attributename] + '\' AND ';
}
}
selector = selector.substring(0, selector.length - 4)
console.log('DEBUG: Selector String: ' + selector);
headers = {
destination: '/topic/virtualtopic',
ack: 'client',
selector: selector
};
if(setFilters)
client.subscribe(headers);
client.on('connected', function() {
client.subscribe(headers);
console.log('DEBUG: Client Connected');
setFilters = true;
});
});
var bufferMessage;
client.on('message', function(message) {
console.log("Got message: " + message.headers['message-id']);
var jsonMessage = JSON.parse(message.body);
if(bufferMessage === jsonMessage){
console.log('DEBUG: recibo un mensaje repetido');
return 0;
}
else{
console.log('DEBUG: Cool');
socket.emit('eventoCajero', jsonMessage);
}
client.ack(message.headers['message-id']);
bufferMessage = jsonMessage;
});
socket.on('disconnect', function(){
console.log('DEBUG: Client disconnected');
if(setFilters){
console.log('DEBUG: Consumer disconnected');
client.disconnect();
}
});
client.on('error', function(error_frame) {
console.log(error_frame.body);
});
});
Looking in the Socket.IO documentation, I've found that this is a known issue (I think critical known issue) and they have not fixed it yet. So, to correct this is necessary to reconnect to the socket in the client side to avoid duplicate messages, using:
socket.socket.reconnect();
function to force reconnection explicitly.

appengine channel no messages arrive

I am trying to get the channel api working.
This is what I have so far:
in the view:
def channel_test(channel_token):
tries = 1
logging.info('starting channel_test')
for attempt in range(tries):
message = 'this is message number: ' + str(attempt)
channel.send_message(channel_token, message)
logging.info('just sent: ' + message)
logging.info(channel_token)
def viewfunc():
channel_token = channel.create_channel('aosasdf123')
deferred.defer(channel_test, channel_token, _countdown=10)
return render_template('Main/cycle.html', form=form, channel_token=channel_token)
and in my template:
<script type="text/javascript" charset="utf-8">
function tell_user(message) {
$('#CycleChannelMessages').append(message + '<br />');
}
function onOpened() {
console.log('onOpened');
var connected = true;
tell_user('ready to take messages');
tell_user('{{ channel_token }}');
}
function onMessage(msg_obj) {
console.log('onMessage');
tell_user('something');
// tell_user(msg_obj.data);
}
function onError(obj) {
console.log('onError');
}
function onClose(obj) {
console.log('onClose');
}
var channel = new goog.appengine.Channel('{{ channel_token }}');
var socket = channel.open();
socket.onopen = onOpened;
socket.onmessage = onMessage;
socket.onerror = onError;
socket.onclose = onClose;
</script>
But the only output I get is from onOpen:
ready to take messages
channel-1788270053-aosasdf123
And in the console I only see:
onOpened
So no other function has been run. The logs from the appengine launcher, clearly shows that the deferred function is being run and it is causing no errors or warnings.
Now what did I do wrong since nothing is showing up at the front-end.
This is on the dev-server BTW. I have not tried it in production yet.
Framework is Flask if that makes any difference.
You pass the client_id to send_message not the channel_token. So your code should be:
channel.send_message('aosasdf123', message)
You place the channel_token client-side for opening the channel, and keep the client_id secret on the server-side for transmitting messages to that client via the channel.

Categories