Reusing websockets between pages? - websocket

Is there a way to open a websocket on one page and then reuse it on another page (within the same tab, after a user clicks on a link, for example) rather than have to open a new websocket after each page load? Is browser storage able to hold onto an open socket?
The aim is to be able to keep to one websocket per user (or tab) and it would be great to do this without needing to move between pages in a non-traditional way, for example loading content into a div using Javascrpt each time the user interacts with the page.

The answer is no.
Even if the socket is not explicitly closed by calling mySocket.close();, the socket will be closed by the browser on reload.
I tried storing the Web Socket object in local storage and using it to retrieve data again. The object returned is valid, but the connection in not there anymore. Because, when the page reloads, the socket is ungracefully terminated.
Message at server side says:
[Errno 10053] An established connection was aborted by the software in your host machine
There you go...

A different approach would be to keep the user instead of the socket across different pages. By that i mean you store the client's ID in a cookie with javascript, each time the user try to open a new socket from any of your website pages, you send this ID to the server and then the server have a way to know that this new connection is from the same user.
I've done that in a recent project and it work perfectly :) Depending on what you are planning to do, you can keep the state of the user on your server with his ID, or store it in an other cookie, or event use flash to store it in a shared object !

Shared Web Workers would allow you to share a WebSocket connections for multiple tabs that are loaded from the same origin/site.
Shared Web Workers are only currently supported on Chrome, Safari, Opera.

Related

when should a web server do accept to create a new client, or reuse the same client?

In a Webserver for basic static website non-blocking event-driven, I don't understand the mechanics I should implement for a "new client".
When a browser connects to my socket, I get the clientfd from accept and answer with a HTTP response, but when the browser is reloaded, should it create a new connection and answer, or should it reuse the same connection and just send the new response?
I use poll to handle multiple fds, but when I reload the page its the same connection (for me this makes sense) but then I open a new tab, and it's still the same connection (It only does accept once). I'm not finding any documentation on this, and I don't have a way to test with multiple client's if it reuses the same one every time.
You can't reuse a connection from another client, new connections must always be accepted as new connections. It doesn't matter what kind of server application you're writing.
However, if the client passes the header Connection: keep-alive you should not close the connection once the response is finished, but keep the connection open for future requests from the same client.
I hope i understand correctly,
but anyway, What i personally do is create a map of sockets, each socket is a client.
Every time a socket disconnects, it's being removed from that map... and so on...
Whether to use a new connection is the browser's choice. You don't get much of a choice.
However, you can tell the browser that you don't allow it to reuse a connection, if you send Connection: close in the response. In this case, the browser is forced to open a new connection for the next request. This is the only control you have.
If you want to test several connections at the same time, you could open several different browsers, or you could use a different program, such as some HTTP load testing tool (there are many). You could also send it a web page with many images; browsers should try to download all the images using several connections at the same time.
A web server doesn't create clients. A web server has clients -- new clients trying to connect, and existing clients communicating on the sockets that it has already opened.
To handle new clients, a web server should pretty much be calling accept all the time, unless it's already handling the maximum number of clients that it's configured to handle.
As soon as you get a new connection from accept, hand it off to other threads to process and call accept again.

Wicket Web Sockets cannot work with multiple browser windows

I created a Web-Socket application in Wicket having a server that pushes messages to all clients. After registrating the clients (application, sessionId and Key (PageId)) the server pushes the messages. So far so good. But if I have multiple browser windows of the same browser on the same client, only one window receives the message and processes it.
Do all browser windows (of the same browser) share the same sessionId? If yes, is there a way to differ between them?
All browsers (from the same vendor, e.g. Firefox) will share the same session id. But if the page id is different then there will be separate web socket registrations and all of them will have their own connection, i.e. all of them will be able to send/receive messages.
If you need to be notified by Wicket when the user opens a second tab/window for the same page id then use org.apache.wicket.ajax.AjaxNewWindowNotifyingBehavior on the page. Most probably you will want to use setResponsePage(page.getClass()) to create a new instance of the same page and have a new WebSocket connection for it.

Websockets or AJAX or both?

I am a bit confused about how one uses websockets. I have already set up a websocket server and are able to receive from server and send to server.
My question is. When using websockets, are you supposed to drop the ajax part completely? Or are you supposed to use websockets alongside ajax?
Example:
I want to use websockets on a chat service on a website where users can log in. When logging in, I use ajax. When on the message page I use websockets to receive future messages, and send future messages. But when navigating to the messages page, I use ajax to get the messages from database.
Is this the correct way of using websockets? Or should I do everything in websockets since 1 user 1 active connection is more efficient? Or should 1 user have 1 websocket connection, but still keep sending ajax requests to the server when navigating to some pages without reloading the site, using ajax?
What is the best practice when creating a large application where users can log in, navigate to pages to load stuff async, but still wanting that bidirectional real time benefits of websockets on stuff like messaging services and notification services on that same website?
There is no reason you cannot use both. I think the solution depends on what server side resources you are using. I may need access to a server through websockets to get updates to a chat dialogue. I may use a completely different system to get user statistics or provide authentication.
I don't think there is a specific answer to your question as it varies depending on the application in question.

Socket.IO : What is the recommended pattern for server side cleanup?

Is it enough to cleanup on disconnect? What happens if a browser disappears before sending an explicit disconnect?
What is the recommended pattern for server side cleanup, so that the resources bound to the connection are not leaked (e.g. Namespace)?
(using gevent-socketio, if it matters)
If you use WebSockets as transport, it would automaticaly disconnect the socket on browser close.
If you use xhr-polling for example it would not automaticaly disconnect (speaking about gevent-socketio).
My approach when xhr-polling is used was:
Saving the socket session id among with logged in user id in database
On next user login detect if such a record exists
Use the stored session id in the record to disconect the unused socket since the fresh user login would generate new socket
This is not rapid solution since you may have unused sockets connected until new login is performed by the user, but it performs a kind of cleanup when the user log in.
This article may be a hint to something more creative than mine solution: http://flask.pocoo.org/snippets/71/

How to send data to client browsers when a server side change occurs

I have an intranet based CRM application developed in CodeIgniter 2.1 where the application is running on a local Apache server and around 20 clients are accessing it over LAN. This is to be connected to a call center setup where the call center application (running on a separate server) will do a HTTP post with caller's number as well as terminal number of the agent where the call is arriving to a URL of my Codeigniter application. I am using this data to populate a database table of call records.
Now from the terminal number (each terminal has static IP, and a session in Codeigniter is linked to IP as well) I can find out which user (login session) of my application is about to receive the call. I want to find a way out how I can send data from server side (it will be regarding the call like the number who is calling, past call records etc.) to that specific user's browser via AJAX or something similar? The agent's browser needs to display this information sent from server.
Periodic polling from browser by jquery etc. is not possible as the data needs to be updated almost instantaneously and rapid polling up to this extent will lead to high CPU usage at client end as well as extra load on network.
P.S.: I only want to know how to modify the browser data from server end.
In AJAX, asynchronous request/response doesn't involve polling; there's just an open TCP connection and non-blocking I/O. The client makes a request but returns immediately; when the server sends the response, the client is notified. So you can achieve what you want with AJAX's XMLHttpRequest without polling[1]. All you need is a url from which to serve your notifications. You could have one request thread and a general dispatch method, or different urls and different threads for each, depending on how you needed to scale.
[1] Well, to be honest, with very little polling. You'd really need to establish what the session/global timeout was and reissue requests within that time limit.

Resources