I have a java client and I need to rewrite it in (client-side) javascript.
I open the java Socket like this:
Socket socket = new Socket("127.0.0.1", 5015);
So I tried to use websocket in javascript:
let socket = new WebSocket("http://127.0.0.1:5015");
but here I have a js error:
Uncaught DOMException: Failed to construct 'WebSocket':
The URL's scheme must be either 'ws' or 'wss'. 'http' is not allowed.
I tried also to use the 'ws' or 'wss' protocol but the server didn't want to handshake with such protocols.
Is there a way to make such socket connection in client-side javascript or it's definitely prohibited?
The answer is a little more complicated than "no you can't do it".
Javascript in a regular web page running in a web browser cannot open a plain socket. The fundamental reason is that it is a security risk for the user. So it is intentionally not allowed.
WebSockets are the secure way to do this. In conjunction with other browser security mechanisms, they limit what a web page is permitted to connect to.
However, that is not the end of the story. It is possible (at least in theory) for trusted code to send and receive TCP and UDP traffic. The problem is that the APIs for doing this are non-standard (e.g. browser specific). In some cases are themselves implemented as 3rd-party browser extensions.
So if you really wanted to pursue this for you application, you are going to have to distribute your code as a trusted browser plugin / extension AND deal with a range of browser portability issues.
It is worth noting that there was a W3C Working Group that was trying to standardize raw socket APIs, but they have officially abandoned their efforts. Their last working draft can be found at:
https://www.w3.org/TR/tcp-udp-sockets/
Finally, there is the problem that a trusted browser extension / plugin requires the user's consent to install. Getting informed consent for something like this is difficult, given the deep and subtle security issues associated with embedding this kind of functionality in the user's browser.
No, you can't make an arbitrary TCP connection from a web page in any browser.
Web Sockets are fundamentally different than TCP sockets... they're essentially unrelated. They're a thin layer on top of HTTP along with a client API which allows bidirectional communication between a Web Socket client and a server supporting Web Sockets.
There are proxy servers you can run that allow connecting through them to make TCP connections, but this of course is a server feature and not something you can do in-browser alone.
The opening handshake is intended to be compatible with HTTP-based
server-side software and intermediaries, so that a single port can be
used by both HTTP clients talking to that server and WebSocket
clients talking to that server. To this end, the WebSocket client's
handshake is an HTTP Upgrade request:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
https://www.rfc-editor.org/rfc/rfc6455
WebSockets server must be able to handle HTTP requests!
I am trying to understand the basics of the internals of HTTP servers and clients with regards to how they transmit data. I have read many articles about how HTTP works but I haven't found any that answers some of my questions.
I would like to go trough the process of loading a web page as I understand it and I would appreciate if you make me notice where I got it wrong.
When I visit a site my browser asks for an HTML file to a server, for that my browser creates a socket, binds it to my ip adress, and connects it to a listening socket of the server of the site I am visiting. In order to connect my browser's socket to the server I need a port number and a hostname, the port number is 80 because this is HTTP and the hostname is obtained via DNS resolution. Now that there is a connection between sockets my browser sends a GET request. That request is an ASCII file with the contents corresponding to an HTTP request. My browser writes the ASCII raw bytes to the socket and that is written to the server's socket.
The server writes back the HTML file I requested to the socket. The HTML the server sends is just an ASCII file that the server will write byte by byte to the socket.
My browser recieves the ASCII file and parses it. Lets assume here that it finds an image tag. The browser sends an HTTP request for that image file. Here comes something I don't understand. How does the server respond? As far as I can tell the server must send back an ASCII file formed by a set of headers followed by a CRLF and then the body of the message. In this case, assuming my browser asked for a .jpeg, does the server write the headers as ASCII plaintext to the socket and then writes the raw bytes of the image to the socket?
If the HTML file has several images do we open a socket per image (per request)?
Lets assume that my browser now finds a javascript tag. When the server answers to my request for that script does the server writes the ASCII bytes of the source of the script to the socket? What happens with js libraries? Does the server have to send all the source code for each one?
On writing data to the sockets: is write(2) the correct way to do all this writing between sockets?
On the transmission of large files: if I click a button on the site that lets me download a large PDF, how is this accomplished by the server? I assume that the server tries to transmit this in pieces. As far as I can tell there is an option for chunked encoding. Is this the way? If it is, is the file divided into chunks, and these are appended to the ASCII response and written byte by byte into the socket?
Finally, how is video transmitted? I know video encoding and transmission would require entire books for a detailed explanation but if you could say something about the generalities of video transmission (for example in youtube) I would appreciate it.
Anything that you could say about HTTP on the socket level would be appreciated. Thanks.
All my answers below relate to HTTP/1.1, not HTTP/2:
3.-My browser recieves the ASCII file and parses it. Lets assume here that it finds an image tag. The browser sends an HTTP request for that image file. Here comes something I don't understand. How does the server respond? As far as I can tell the server must send back an ASCII file formed by a set of headers followed by a CRLF and then the body of the message. In this case, assuming my browser asked for a .jpeg, does the server write the headers as ASCII plaintext to the socket and then writes the raw bytes of the image to the socket?
yes it does, usually. It's possible that it's encoded in a different format (gzip, brotli) or it might be chunked if a Content-Length was not set.
4.- If the HTML file has several images do we open a socket per image (per request)?
In HTTP/1 modern browsers will open up to 6 sockets per host but not more. If there's more than 6 requests going to the same host, it will wait until the other responses have been received.
5.- Lets asume that my browser now finds a javascript tag. When the server answers to my request for that script does the server writes the ASCII bytes of the source of the script to the socket? What happens with js libraries? Does the server have to send all the source code for each one?
Usually yes, you need 1 http request per javascript file. There's some server-side tools that combine javascript sources along with their dependencies in a single javascript 'file'. Note that javascript sources are typically UTF-8, not ASCII.
6.- On writing data to the sockets: is write(2) the correct way to do all this writing between sockets?
Dunno! Not a C guy
7.- On the transmition of large files: if I click a button on the site that lets me download a large PDF, how is this accomplished by the server? I assume that the server tries to transmit this in pieces. As far as I can tell there is an option for chunked encoding. Is this the way? If it is, is the file divided into chunks, and these are appended to the ASCII response and written byte by byte into the socket?
No, chunked is used for HTTP responses for which the content-length is not known ahead of time. The 'splitting up' you're talking about is done on a IP/TCP level, not at the HTTP protocol level. From a HTTP perspective it's just one continuous stream.
Finally, how is video transmited? I know video encoding and transmition would require entire books for a detailed explanaition but if you could say something about the generalities of video transmition (for example in youtube) I would appreciate it.
Too broad for me to answer.
It is highly recommended to read High-Performance Browser Networking.
About HTTP
HTTP is a message structuring protocol. It can be built on top of TCP/IP, or UDP, or any other communication protocol.
IP solves the problem of figuring out which computer in a network a message is meant to get to, and TCP solves the problem of ensuring the message gets received despite noise interfering. UDP does what TCP does, but without some important guarantees that make it better in some situations, such as video streaming.
HTTP only solves the problem of what the messages should look like so everyone can understand what you mean. An HTTP message consists of a header and a body. The body is the message you want to send; the header contains meta-information about the status of the message itself. HTTP lets you structure your applications in a meaningful, context-oriented way through a standard set of terms.
For example, you can communicate character encodings of your body with HTTP, how long your content is, whether you are okay with receiving it in a compressed format, and so on and so forth. So, no, HTTP is not limited to ASCII texts - you can send UTF-8 encoded characters with BOM markings, or not even specify an encoding at all. All HTTP does is let you ask for things in the way you want it, and inform recipients how you've packaged a message.
The actual thing responsible for handling how your messages are sent rather than structured are TCP/IP and UDP. HTTP has nothing to do with it. Both TCP/IP and UDP add overhead, but are well worth it so that communication can pass through unimpeded.
About Sockets
Computers listen on "sockets", which is just a fancy name to refer to a communication channel. It does not matter what a socket is - it is just a generic name used to refer to a communication channel, be it a wire or a wireless radio. All that matters is what a socket can do. Computers can send bytes down a socket (called flushing), and can read bytes sent through a socket. Sockets always carry a certain amount of memory reserved for incoming messages (like an inbox) called a buffer, and can even bundle many messages together and send them together in one shot to save time.
Sockets at the hardware level usually devolve to a network card, which lets you talk to wireless network, or to an Ethernet cable. Note that the computer may have many more sockets than cables - this is because a socket is a generic name for a single communication channel, and a single network/ Ethernet card can handle multiple communication channels. Being able to handle multiple channels at once is called multiplexing.
TCP/IP and UDP are just blueprints - it is the responsibility of the operating system to actually do as they lay out, and most OSs have some program designed to implement these standards. At the software level, how information is read and written becomes slightly more complicated than just passing bytes since a computer must also be able to interrupt its running programs when a hardware event happens, including while communicating from a socket - here is a reference for how the Linux kernel implements TCP/IP.
All operating systems expose a set of calls to start listening to (bind) a socket, read a socket and write to a socket. You can read from a socket in multiple ways, however. These range from the basic select() and [poll()] in most Linux distributions, which force the program to wait until all the data requested for has been received and then read it, to epoll() in Linux as well, which enables a program to ask to be notified when data has been received before having to read it.
Windows exports a completely different set of system calls, so you would be well advised to consult a reference manual for the same if planning to build applications for Windows.
About TCP/IP
TCP/IP is a combination of two protocols that has mostly become the norm for ensuring reliable communication.
IP is responsible for the term IP address. Every computer has a unique address associated with it, specified as either a 32-bit number (IPv4) or a 128-bit number (IPv6, or IP version 6). Note that these addresses do not exist outside of a network: a network is just a collection of computers, and a computer's address only makes sense within that collection. The network that the computer comes from is part of the IP address of a computer; the network itself is given a unique address; and a network may be composed of multiple networks. The IP protocol introduces the concept of a port, which is essentially synonymous with the concept of a socket.
I'm just tossing about the term 'network' willy-nilly as an abstract concept, but physically it boils down to a router. A router is a special computer responsible for figuring out who is being referenced to in a message using the IP address attached to the message, for assigning IP addresses to computers it is aware of (a network is quite literally the set of computers the router knows about), and for forwarding messages to other computers or routers. An internetwork (or just the Internet) is simply a bunch of routers, each with their own network, able to communicate to each other to form one giant network of connected networks. Effectively, a router implements the IP standard.
TCP and UDP are designed to solve another harrowing problem: how to ensure all of your messages get through. Sending any message down a shared communication channel like wireless or even wired channels organised like a bus topology is inherently messy - different messages can overlap, messages can be lost unexpectedly, messages can be corrupted and so on. TCP aims to solve these problems by guaranteeing all of a message goes through. On the other hand, UDP makes no such guarantees, and thus saves time by skipping a lot of steps TCP does.
TCP and UDP chunk the message into packets of a certain size, so that a message can be sent out as quickly as possible. TCP further adds some additional structure to the exchange called a three-way handshake:
It sends off a TCP-specific message called a SYN packet to the computer it wants to send a message to, and waits for a response.
If the target computer receives it, it responds with a SYN ACK packet. On receiving this, the source computer responds with an ACK packet. This lets both computers know each other is listening, and they can start sending packets.
On the other hand, if either the source or target computer don't hear anything after a while, they wait for a while and send again, and wait some more. Every time they have to wait, they wait for twice as long as they did last time, until a maximum wait period has been reached and they abort a connection. This is called exponential backoff, and is key to TCP.
A three-way handshake ensures everyone is ready and willing to listen. However, the fun doesn't stop there:
As part of the handshake, the source computer specifies it will fire off an initial certain number of packets, each of a certain size.
After the handshake, the source computer fires off the specified packets, and waits for an ACK for every packet sent. If it doesn't receive an ACK for any packet, it goes into exponential backoff before resending that packet
Meanwhile, the target computer has been told to await a certain number of packets, so it waits until all of them are in. Packets may arrive out of order, depending on how the intervening networks routers chose to optimise the path for each packet, so each packet is prepended with a certain message indicating their order, and the target computer sorts them together into one neat message.
Once the source receives an ACK, it uses the total time taken to see how much it can send next. The better the response time, the more packets TCP is willing to send.
UDP skips the three-way handshake. It only chunks and sends. It is not guaranteed all of your message will get there. It is not guaranteed it will be sent in order (as opposed to received in order). It is perfect for cases where high network reliability means most of your messages will probably arrive, but where it doesn't matter if all of it arrives (e.g . it is okay if some frames in a video don't arrive).
About Video
Video is fundamentally no different from any other content format. It is perfectly possible to use HTTP for videos. Whether it is advisable to use TCP is another matter, but isn't bad - Skype uses both UDP and TCP.
All video consists of a series of bytes. How those bytes are to be interpreted is the job of the encoding. Video can have many encodings: avi and mp4 come readily to mind. With HTTP, you can specify the content encoding as part of the message headers.
HTTP enables compression of content, including for video. HTTP also allows you to request that a connection be kept-alive i.e. that a three-way handshake need not be performed again after a full message has been sent. An extension to HTTP called websockets was developed that effectively use these two features to provide support for real-time video passing. These only optimise the video arrival so it doesn't look laggy, but it doesn't change how the video arrives.
Of course, sometimes you want more guarantees about video, and there are lots and lots of tricks to use to support high-fidelity video in low-speed Internet environments, or enable multiple people to subscribe to a live broadcast, etc. That's when you have to get creative. But otherwise video content is not fundamentally different from any other content type.
To Answer Your Questions
When I visit a site my browser asks for an HTML file to a server, for
that my browser creates a socket, binds it to my ip adress, and
connects it to a listening socket of the server of the site I am
visiting. In order to connect my browser's socket to the server I need
a port number and a hostname, the port number is 80 because this is
HTTP and the hostname is obtained via DNS resolution. Now that there
is a connection between sockets my browser sends a GET request. That
request is an ASCII file with the contents corresponding to an HTTP
request. My browser writes the ASCII raw bytes to the socket and that
is written to the server's socket.
HTTP does not require port 80. It is a convention that port 80 be the default port for HTTP-using servers and 443 for HTTPS, but any port can be used, so long as no other port is occupied.
You do not receive a hostname from DNS. Actually, it's the opposite - you supply a hostname, and retrieve an IP address from DNS. It is the IP address that is used to identify a location on another network.
It is not necessary for the response to be ASCII. Headers, yes, are to be interpreted as ASCII as they are part of an international standard that was developed before UTF-8 gained prominence, but no such restrictions are needed on the body. In fact, the content encoding is traditionally passed along as a header itself, which the browser or a client can use to decode the body content automatically.
The server writes back the HTML file I requested to the socket. The
HTML the server sends is just an ASCII file that the server will write
byte by byte to the socket.
Yes, except there is no need for it to be ASCII.
My browser recieves the ASCII file and parses it. Lets assume here
that it finds an image tag. The browser sends an HTTP request for that
image file. Here comes something I don't understand. How does the
server respond? As far as I can tell the server must send back an
ASCII file formed by a set of headers followed by a CRLF and then the
body of the message. In this case, assuming my browser asked for a
.jpeg, does the server write the headers as ASCII plaintext to the
socket and then writes the raw bytes of the image to the socket?
Yes.
If the HTML file has several images do we open a socket per image (per
request)?
See this answer. HTML is always downloaded first before the image requests are fired off, and images are always requested for in the order that they are encountered in the DOM. If you have 24 images on Chrome, 6 of them will be loaded in parallel at a time, meaning four parallel connections.
You can additionally answer this yourself by opening up your Network tab in the Chrome console, and inspecting whether requests for images are fired off in parallel.
Lets assume that my browser now finds a javascript tag. When the
server answers to my request for that script does the server writes
the ASCII bytes of the source of the script to the socket? What
happens with js libraries? Does the server have to send all the source
code for each one?
The HTML specification allows you to select what order you want your Javascript files to be downloaded.
Yes, the server writes bytes. The bytes do not need to be ASCII-encoded. The headers will be in ASCII. Yes, the server must send the source code for each library. This is why an important part of web optimisation is minimising your Javascript file sizes and bundling all the libraries into one file, in order to reduce the number and size of requests.
On writing data to the sockets: is write(2) the correct way to do all
this writing between sockets?
It is certainly the most basic way to write to an open file descriptor on Linux kernels. Everything in Linux is treated like a file, including sockets, so yes, sockets have file descriptors and can be written to this way.
There are more complex ways of accomplishing this, all of which are referenced in the manual page for write. Most languages have support for writing to sockets, however, by having glue code to manually call write() using a friendlier interface. Perhaps the only time you would need to explicitly call write() in C is if you were writing kernel-level programs or are on embedded hardware.
On the transmission of large files: if I click a button on the site
that lets me download a large PDF, how is this accomplished by the
server? I assume that the server tries to transmit this in pieces. As
far as I can tell there is an option for chunked encoding. Is this the
way? If it is, is the file divided into chunks, and these are appended
to the ASCII response and written byte by byte into the socket?
See the TCP/IP section I wrote above. The HTTP standard does let you get away with breaking up a message into higher-order chunks before letting TCP chunk it still further, so you can make do with small segments that arrive at a time.
Finally, how is video transmitted?
See the video section I wrote above.
HTTP, sockets, streaming and packages transmition are different topics.
HTTP is a communication protocol to request or send data. Sockets are not used regularly by web developers because they are not very network friendly, due to the persistent connection required. How your browser manages the HTTP requests usually should not be a real concern for you.
For big chunks of data like video, streaming is maybe the best technique, because you don't need synchronization between the client and server, or an always active connection like with sockets.
The way streaming is done only depends on you and on the language you have on the server to share your content.
If you want to learn more about HTTP, I recommend to you to read a little on RFC's like RFC 7230 or RFC 7231.
To understand how data is transmitted you should really know the basis of Abstraction Layers and for video streaming, you might learn how to make one video streaming server with NodeJs, (you might pick another language of your preference), or just search and install an NPM package that already does that job for you.
i created TCP Client Using Web Socket 'JavaScript' and it can connect to C# TCP Server but i can't replay in C# to handshaking sent by JavaScript TCP Client
Please Help !
thanks.
There's no way we can help you here in any specific way without seeing your code on both client and server. webSocket is a protocol, not just a plain TCP connection. For your C# server to successfully accept a webSocket connection from any client, it must follow the entire webSocket protocol.
This reference Writing WebSocket Servers provides a pretty good summary of what a server has to do in order to successfully "speak" webSocket. Unless this is merely a learning exercise for you, you will probably want to get a library/class for C# that already implements a webSocket server as I'm sure there are many.
To give you a general idea, all webSocket connections start with an HTTP request that includes an "upgrade" header, a security key and a version. If the server agrees to the upgrade, then it responds with a security key. At that point, the two sides switch from HTTP to the webSocket protocol on that same socket and from then on, all data is then sent using the webSocket Frame format. This information is all outlined in the earlier MDN reference about creating webSocket servers.
Here is an article about writing webSockets servers in C#:
MDN: Writing a WebSocket server in C#
I've read about WebSockets but they don't seem to be pure "sockets", because there is an application layer protocol over them. "ws:"
Is there any way of doing a pure socket connection from a web browser, to enliven webpages?
Here are my random stabs in the dark
Applets sockets provided by Java (need java installed)
Flash sockets provided by Flash (need flash installed)
But about HTML5, Why are they called WebSockets if they aren't Sockets?
Is the websocket protocol so simple to implement that it is "almost"-sockets?
I've read about WebSockets but they don't seem to be pure "sockets", because there is an application layer protocol over them.
[Is the] websocket protocol so simple to implement that [it is] "almost"-sockets?
Allowing regular socket connections directly from the browser is never going to happen because it opens up a huge risk. WebSockets is about as close to raw sockets from the browser as you are going to get. The initial WebSockets handshake is similar to an HTTP handshake (allowing web servers to proxy/bridge it) and adds CORS type security. In addition, WebSockets is a message based transport (rather than streaming as raw TCP) and this is done using a two byte header on each message frame.
Even flash is not able to quite make raw TCP connections. Flash sockets also add CORS security, but instead of an in-band handshake, flash socket connections make a connection to port 843 on the target server to request a security policy file.
Is there any way of doing a pure socket connection from a web browser, to enliven webpages?
Yes, you can use my websockify bridge/proxy which allows a WebSockets enabled browser to connect directly to a TCP socket via websockify.
But about HTML5, Why are they called WebSockets if they aren't Sockets?
WebSockets are a transport built on TCP sockets. After the handshake there is very minimal overhead (typically just a two byte header).
I can't improve on Kanaka's answers to your secondary questions, and I know this question is a year old. But for the main question, Is there any way of doing a pure socket connection from a web browser, to enliven webpages? There is a project called the Java / JavaScript Socket Bridge that might be what you (or anyone coming across this page from a Google search) are looking for. The advantage of this method over what others have mentioned is that it does not require either a client-side or a server-side service to be run. So, for instance, if you wanted to implement an IRC client purely in JavaScript but your web host does not allow you sufficient rights to proxy the connection, this Java applet would be the way to go. The only concern is making sure the client has Java installed and allowed.
You can just send data between a client and a server with WebSockets. Simply speaking, the only difference that WebSockets introduces is that the client:
adds some header bytes, like the type of data and the length
adds masks and encodes the data using them
The server also has to add header bytes, but does not need to encode the data.
If you implement the protocol correctly (server side, that is, since the browser already has an implementation), you can use it with ease to send text and binary data. (Although browser support is narrow, especially for the latter.)
The benefit of WebSocket is that it is HTTP based. You can use it also in environments there http proxies are used. Thus Websocket has a higher infrastructure compatibility as plain tcp.
Additionally http/WebSocket is providing you some features which you otherwise have to specify on your own:
Redirect
NAT keepalive
Multiplexing via URI
Framing
If you are asking for some data to be pushed from server it is widely termed as COMET or Reverse Ajax.
Web sockets is still not very popular as there are inherent firewall issues and minimal support yet from popular browsers.
You can take a look at http://www.ape-project.org/ as this is one of the most popular implementations (but native to unix/linux only for now. For windows they suggest using a virtual box or vmware based implementation)
I have PHP on the server side, and HTML and javascript on the client side.
I am making an app where a stakeholder types a message that is broadcasted to multiple recievers of a group in real time.
I did some research on google and I understand I need to use WebSockets or Comet for real time push notifications. Is WebSocket or Comet mandatory for sending mass notifications to users?
Is my understanding correct? Any references to start with?
If the client is a browser, then the ONLY two ways a standard browser can connect to a server is via an Ajax (e.g. http) request or a webSocket connection. So, if you want a client to get notified of something from the outside world it has to use one of those two mechanisms.
HTTP requests are transitory. The client makes a request of a server, the server responds. HTTP requests are perfect for the client requesting information from the server. They are not very good at the server sending information to the client because normally the client is not connected. There are hacks and work-arounds where the client "polls" the server on some interval and maybe even the server uses longer running requests to try to simulate a "push" type system, but they are sub-optimal hacks at best.
webSockets are continuous connections. The client connects and the connection remains in place for as long as both sides want. This allows either side the ability to send a message to the other side whenever they want. That means the server can "push" data to the client whenever it wants. webSockets are efficient for push connections and are recommended (this is one of the main things they were designed for).
Comet is a library that was originally built for using HTTP to try to "hack" or "simulate" push before webSockets were invented and then before they were widely supported. I can think of no reason why one would want to use Comet instead of a webSocket unless you had such an old browser that webSocket was not supported.
So, if you are trying to do "realtime server push" to a browser, then you must have a continuously connected socket from the client which means webSocket (or something built on top of webSocket like socket.io).
For phone apps where you have access to the phone SDK, you can use the "push" system built into the OS to push some messages from server to client. This isn't quite the same as the two way webSocket channel, but since you asked about "push notifications", the OS push services available in both Android and IOS could also be an option for pushing notifications from server to client. Here's info on iOS notifications and Google Cloud Messaging
As of 2016, one can also use Server-sent events in all modern browsers except Microsoft browsers (not supported yet in Edge or IE) to push data from server to client. Here's a browser compatibility table. Server-sent events use a long lasting HTTP connection, a special MIME type and a supporting client in order to be able to send events from server to client at any time. Unlike webSockets, server-sent events are one way only (from server to client). A client would then use a traditional Ajax call in order to be able to send data to a server (whereas with a webSocket data can be sent either way over the same webSocket connection).
Here's a good description of how server-sent events work: How do server-sent events actually work?
Is your client application a SPA? (Single Page application)?
It's very important because if not, you have to consider that everytime a client change page, connection with websocket server will be lost.
In this case you have to manage a queue because if stakeholder send a multicast request when one client is disconnected, client won't receive nothing.
Polling won't solve this situation too and it's an orrible solution because mobile clients (for example) with typical internet plan, will consume megabytes for unuseful "ping" traffic.
A real example of polling is a child in a car asking his dad every minute if they are arrived to a destination!
So, Is there a solution without using spa?
Yes, using a "shared storage" between stakeholder and clients, and using websocket only for "wake up" online clients saying: Hey there is something new, go to check!
Everytime a client open a page it will receive from backend also not-read notifications, taken from the storage.
When a stakeholder want to notify something, it will just store the notification message in the shared storage and send a "pulse" to notification server.
Notification server will forward the "pulse" to online clients (just in case someone is stuck reading a page).
If a "pulse" is lost because a client is changing page there is no problem because the client will bring notifications from the storage.
Every page will contain this logic:
Retrive number or unread notifications (server side)
Connect to the notification server after 5 seconds (javascript side).
Hope it helps.
I would suggest that using webSockets is a more efficient way compared to other options, why is this? Well when a client receives a notification that there's a change in the server there is no need to create an AJAX call to the server to get that change, it can be sent to the client with the same webSocket connection more easily than AJAX. This means efficient code and a faster running App!