Establishing WebSocket Connection within and for a JS API - javascript

Aim: In order to provide a simple, easy-to-use JS library that communicates with a server I am trying to establish a WebSocket connection at the start of my API and define the library's functionality thereafter.
Problem: The issue is that my socket's readystate does not transition to 1 (ready) before the library is loaded and the user's script is run. Debugging this has confirmed this and I'm not sure how to ensure my WebSocket is established before proceeding with the user's script.
What I have:
(function(myObject) {
var socket = new WebSocket(url);
socket.emit = function() {
//do some tasks and create a var "message"
socket.send(message);
}
window.myObject = myObject.prototype = {
doSomething: function() {
socket.emit();
}
}
}(myObject = window.myObject || {}));
Above, I've defined a custom method (socket.emit()) on the socket object that, in turn, calls socket.send(). I do this to manipulate some data before sending it via socket.send(), reusing code that would otherwise be repeated.
Then I have some very basic html that includes this JS library and a simple script runs as follows:
$(document).ready(function() {
myObject.doSomething();
});
The error I get is: "Failed to execute 'send' on 'Websocket': already in CONNECTING state."
The library successfully loads but the Websocket does not complete connection before the client script is run. How can I ensure my WebSocket is connected (readystate == 1) before the API finishes loading?
Thanks for the help!

What you could do is buffer all messages in socket.emit as long as the socket is not connected and send them once you receive the onOpen callback.
While this will handle your current problem you will see that new ones will arise:
You might want to handle disconnects from your server and reconnects and therefore you might need to extend your library API anyhow to also expose connectionstate change events and force the library user to only send messages when connected.

Related

Node JS socket.on() client side glitch?

I am learning Node JS and have come across some strange behavior which perhaps someone knows the answer to. A lot of tutorials posts I have come across are saying to use "socket.on('connect', function(){ blah blah }); on the client side to send a request to the server. Esentially this is supposed to stop a call from being sent to the server until the server has established a connection with the client. However when I test the code, it works as long as the client html is run first, and then node js is launched afterwards. If node js is running the server code first, and then the client side html is launched, the emit function doesn't call out to the server for some reason. If I omit the socket.on function and go straight to my socket.emit function, the server receives the emit function from the client. If node js is not running first, the client side html continues to run until node js launches the server script, at which point the client connects, and emits the request automatically. Does anyone know why this is happening? As I said, I am still learning Sockets and Node JS, so I would rather understand the behavior instead of just continuing on with my coding, even though I got it to work. Any information you provide would be extremely valuable. Thanks.:)
// Server side
var express = require('express');
var socket = require('socket.io');
var app = express();
var server = app.listen(1111, function(){ console.log("Server Listening"); });
var io = socket(server);
io.on('connect', function(socket) {
socket.on('Contact', function(data) {
socket.join(data);
console.log(data); // just to test if data is sent
});
});
// Client in head section
<script src = "https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.7.3/socket.io.js"></script>
<script type = "text/javascript">
var socket = io.connect("http://localhost:1111");
function Setup() { // called when page has loaded
//blah blah blah lots and lots of code
var data = "blahblah"; // room to join
socket.on('connect', function(){
socket.emit('Contact', data);
});
}
// If I remove the socket.on function it works flawlessly everytime. Left in, it will only fire if the
// node js server file is launched after the client launches
It seems like you're calling the Setup() function manually some time later (in the page load event perhaps, based on the comment). This means you're creating a race condition: If the server connects before the page load event, the connect event happens too fast and you attach your listener only after it happens.
So essentially what's happening is this:
First Case (server starts after client)
Client HTML loads, script executes
Client starts attempting connection to server
Client assets finish loading, Setup() is called
Client connect listener attached to socket
Server starts up, starts accepting connections
Server accepts client connection
Client connect listener fires, emits Contact event
Second Case (client starts after server)
Server starts up, starts accepting connections
Client HTML loads, script executes
Server accepts client connection
There is currently no connect listener, so nothing happens
Client assets finish loading, Setup() is called
Client connect listener attached to socket
Silence...
To fix, you should only call io.connect(...) in the same scope that you add listeners to it. This means either moving the socket.on('connect', ...) outside of Setup() or moving the io.connect() inside Setup() (probably better).

Correct way to handle Websocket

I've a client to server Websocket connection which should be there for 40 seconds or so. Ideally it should be forever open.
The client continually sends data to server and vice-versa.
Right now I'm using this sequence:
var socket;
function senddata(data)
{
if (!socket)
{
socket = new WebSocket(url);
socket.onopen = function (evt) {
socket.send(data);
socket.onmessage = function (evt) {
var obj = JSON.parse(evt.data);
port.postMessage(obj);
}
socket.oneerror = function (evt) {
socket.close();
socket = null;
}
socket.onclose = function(evt){
socket = null;
}
}
}
else
{
socket.send(data);
}
}
Clearly as per current logic, in case of error, the current request data may not be sent at all.
To be frank it sometimes gives error that websocket is still in connecting state. This connection breaks often due to networking issues. In short it does not work perfectly well.
I've read a better design : How to wait for a WebSocket's readyState to change but does not cover all cases I need to handle.
Also I've Googled about this but could not get the correct procedure for this.
So what is the right way to send regular data through Websockets which handles well these issues like connection break etc?
An event you don't seem to cover is onclose. Which should work really well, since it's called whenever the connection terminates. This is more reliable than onerror, because not all connection disruptions result in an error.
I personally use Socket.IO, it enables real-time bidirectional event-based communication between client and server.
It is event driven. Events such as
on connection :: socket.on('conection',callback);
and
on disconnect :: socket.on('disconnect',callback);
are built in with socket.io so it can help you with your connection concerns. Pretty much very easy to use, check out their site if you are interested.
I use two-layer scheme on client: abstract-wrapper + websocket-client:
The responsibilities of the websocket-client are interacting with a server, recovering the connection and providing interfaces (event-emitter and some methods) to abstract-wrapper.
The abstract-wrapper is a high-level layer, which interacts with websocket-client, subscribes to its events and aggregating data, when the connection is temporary failed. The abstract-wrapper can provide to application layer any interface such as Promise, EventEmitter and so on.
On application layer, I just work with abstract-wrapper and don't worry about connection or data losing. Undoubtedly, it's a good idea to have here information about the status of connection and data sending confirmation, because it's useful.
If it is necessary, I can provide some code for example
This apparently is a server issue not a problem in the client.
I don't know how the server looks like here. But this was a huge problem for me in the past when I was working on a websocket based project. The connection would continuously break.
So I created a websocket server in java, and that resolved my problem.
websockets depend on lots of settings, like if you're using servlets then servlet container's settings matter, if you're using some php etc, apache and php settings matter, for example if you create a websocket server in php and php has default time-out of 30 seconds, it will break after 30 seconds. If keep-alive is not set, the connection wont stay alive etc.
What you can do as quick solution is
keep sending pings to a server after a certain amount of time (like 2 or 3 seconds, so that if a websocket is disconnected it is known to the client so it could invoke onclose or ondisconnect, I hope you know that there is no way to find if a connection is broken other than failing to send something.
check server's keep-alive header
If you have access to server, then it's timeouts etc.
I think that would help

Error while getting messges from sockets in javascript

Hi i am having trouble with creating a socket communication from java script code.
I am always getting error while sending a message or closing the socket from server.
My Socket server code.
// Start listening for connections.
while (true)
{
Console.WriteLine("Waiting for a connection...");
// Program is suspended while waiting for an incoming connection.
Socket handler = listener.Accept();
data = null;
// An incoming connection needs to be processed.
while (true)
{
int bytesRec = handler.Receive(bytes);
data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
break;
}
// Show the data on the console.
Console.WriteLine("Text received : {0}", data);
// Echo the data back to the client.
byte[] msg = Encoding.ASCII.GetBytes(data);
handler.Send(msg);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
JavaScript code:
var connection = new WebSocket('ws://Myip:11000', ['soap', 'xmpp']);
// When the connection is open, send some data to the server
connection.onopen = function () {
connection.send('Ping'); // Send the message 'Ping' to the server
connection.send('your message');
};
// Log errors
connection.onerror = function (error) {
console.log('WebSocket Error ' + error);
};
connection.onclose = function (msg) {
console.log('WebSocket Error ' + msg);
};
It gets connected to server socket, but always gets error while closing or sending a message from server.
If this is really your actual code:
handler.Send(msg);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
…then it's pretty broken. First, you can't assume that Socket.Send() actually sends all the bytes you asked it to. You have to check the return value, and keep sending until you've actually sent all the data.
Second, the initiation of a graceful closure should use SocketShutdown.Send, not SocketShutdown.Both. Specifying "Both" means (among other things) that you're not going to wait for the other end to negotiate the graceful closure. That you're just done and won't even receive any more data, in addition to being done sending.
And of course, the code is calling Close() before the other end has in fact acknowledged the graceful closure (by itself sending any remaining data it wanted to send and then shutting down with "Both").
Is all this the reason for your problem? I can't say for sure, since I have no way to test your actual code. But it's certainly a reasonable guess. If you tear down the connection without waiting after you try to send something, there's not any guarantee that the data will ever leave your machine, and in any case the other end could easily see the connection reset before it gets a chance to process any data that was sent to it.
There aren't a huge number of rules when it comes to socket programming, but what rules exist are there for a reason and are generally really important to follow. You should make sure your code is following all the rules.
(The rest of the code is also different from what I'd consider the right way to do things, but the problems aren't entirely fatal, the way that the over-eager connection destruction is).
I am afraid WebSocket does not work that way.
When the Javascript code connects to the server, it will send a HTTP request as ASCII text. That request will include a HTTP header Sec-WebSocket-Protocol: soap, xmpp, as you are requiring those protocols in your WebSocket creation.
Since your server code does not reply with an appropiate HTTP response accepting the websocket connection, the connection will fail. When you try to send data back, the client will not recognize it as a HTTP response and a error will be thrown.
A websocket is not a regular socket connection, it won't work that way. It requires HTTP negotiation and there is a schema for data framing. I recommend you to go through this article that explains very well how it works: http://chimera.labs.oreilly.com/books/1230000000545/ch17.html
If you are interested in learning how to develop a server, take a look to this tutorial in MDN: https://developer.mozilla.org/en-US/docs/WebSockets/Writing_WebSocket_server I also have an open source WebSocket server in C# you can take a look if you like.

How to handle socketIO when app is not running

I've been doing alot of testing with socketIO and have got stuck with handling situations where my node app is simply offline. The documentation provides no real insight into this issue.
So if i run my website and node app is simply not running, console.log gives:
GET http://[url]:[port]/socket.io/socket.io.js
Uncaught ReferenceError: io is not defined
This is hardly surprising, how ever what i don't understand is how to handle these errors and simply have the script try to attempt a reconnect until it finally does reconnect (if ever).
My script looks like this:
<script src="http://[url]:[port]/socket.io/socket.io.js"></script>
<script>
windows.onload = function()
{
socketio = io.connect("http://[url]:[port]");
socketio.on('connecting', function() {
console.log('trying to connect');
});
socketio.on('connect', function() {
console.log('connected');
});
}
</script>
Is there a way to handle this kind of problem ?
When the server is offline, your initial <script> tag to load the Socket.io client library fails, so you never get the io object in the first place.
To retry, you can add a new <script> tag to load the same URL again and see if it succeeds.
Better yet, copy the socket.io client library to the server hosting your HTML, so that the script will always load. You can then simply handle connection errors from io.connect().
There are a few events that you can bind to.
socket.on("connect_failed", function() {
// Do whatever you wanted to do on failure
});
For a full list of exposed events check here: exposed socket.io events
Edit
Ah, I'm sorry. I misunderstood your question. I thought you wanted to handle when the socket server was offline. If you want to handle not being able to get at the socket.io client script, maybe you could check if socket is null or undefined and handle thought that. Then also fire a setTimeout function to try and load the script asynchronously after a wait period and then check if socket is still undefined or null. Or, as the other answer suggests, pack the socket.io client library with the rest of your HTML page.

CFWEBSOCKET - unable to call websocket object in Javascript

I'm using the cfwebsocket tag in Coldfusion to create a web socket connection.
I looked at an example from here http://www.sagarganatra.com/2012/03/html5-websockets-in-coldfusion-10.html
and near the end it shows you all the javascript calls you can make on the web socket object.
However, when I try to make any call on it I get an error that it is undefined.
For example I have:
<cfwebsocket name="ws" onMessage="messageHandler" onOpen="openHandler" onClose="closeHandler" onError="errorHandler" subscribeTo="chat" />
and in my javascript i call
alert(ws.isConnectionOpen());
and I get the error in firebug: TypeError: ws is undefined.
Anyone know why I can't call it?
My chat works fine and I can connect and chat properly. I just wanted to close the connection when the chat ended so I was looking into how it's done calling the websocket but I don't know why it's not working.
Note that I am using jQuery and the javascript is wrapped in the document ready.
First, you can't interact with the ws object till it establishes a connection to the server.
There are a couple of ways to handle this scenario. You can use the "onOpen" attribute and have it call a function once the web socket connect has been established.
However, you are probably better off just using the "onMessage" attribute and create a generic listener function that processes all web socket messages from the server.
function messageHandler(msg) {
if (msg.type == 'response' && msg.reqType == 'welcome'){
alert('user connected');
}
}

Categories

Resources