I am currently working on an instant messaging system. But, I have a problem with the optimization.
Here is my current code:
<script>
setInterval('load_messages()', 500);
function load_messages(){
$('#messages').load('loadMessages.php');
}
</script>
Apart from the fact that, it is better to use an AJAX request to ask only for messages after a defined timestamp. Is there a way to pass a packet from the sender's page to the receiver to refresh to avoid spamming the database.
Here is a schema explaining what I would like to do:
Is there a way in php, apache or javascript to do this?
Thanks for reading
The technique you use is called short-polling. It's basically spamming the server until the server has something new to show you. Looks something like:
Client: cookie?
Server: no
Client: cookie?
Server: no
Client: cookie?
Server: no
Client: cookie?
Server: yes; here's the cookie: 🍪
Client: cookie?
Server: no
...
This is really inefficient, as you understood yourself; I don't know of any websites that still use short-polling.
You have other options. The easiest one (given you are using PHP) is long polling. Basically, you send a request, and the server just stalls the request, and once a new message comes the server sends the response back. This allows you to get messages immediately and not send so many messages:
Client: tell me when you have a cookie...
[loads for 1m 32s]
Server: the cookie has come [sends response]
Client: tell me when you have a cookie...
...
However, Apache handles concurrent requests by creating a new thread per request. So if you have 2 users in your chat, that's fine. But let's say you have many rooms and a total of 100,000 users long-polling your server. Your server probably can't handle that many threads and will crash. (NodeJS is very popular for realtime applications for its event-driven architecture and built-in asynchronism.)
But there are other much, better, options:
Websockets: this is basically a persistent (that is until the connection is manually closed) connection between the client and server, so the client doesn't have to bug the server so much. Whenever the server has a message, it sends it to the client immediately and vice versa. Here's a good article. This is the most popular solution to realtime apps, and implemented by most chat apps like Discord or Slack.
SSE (server sent events): basically, instead of the client asking the server for data, the server can send data to the client. Here's another article if you want to know how it works.
Your context: SSE is quite easy to implement in PHP without extra libraries; here's an example. Websockets, on the other hand, are a bit more complex to set up (may require a third-party library like rachet), but because of how well it works that's probably what I would consider.
Your question: Is there a way to pass a packet from the sender's page to the receiver to refresh to avoid spamming the database? If I were to exactly answer your question, SSE.
Related
I'm building a website, and one of the features is a public chat that anyone online can use. When a message is entered it is sent to the server and then saved to a SQL database. How could I relay this information to all the online clients without them making a request to the server? I've thought about having all clients make a request to the server every 500ms or so but I feel that would be incredibly inefficient. Any suggestions?
What you're looking for is typically called "server push" where the server can unilaterally send data to the client without the client having to "poll" or repeatedly ask for new info.
The two general technologies for server push these days are webSockets and server-sent events (SSE). In both cases, the client initiates a connection to the server and that connection is held open so that the server can send data to the client whenever it wants to without the client having to specifically poll for that data.
A webSocket is a full, two-way data channel. Either client or server can send data in either direction.
SSE is a one-way channel, the server can send data to a listening client.
You can see these articles on comparing the pros/cons of each.
WebSockets vs Server-Sent Events - ably.com
Server-sent events vs. WebSockets - logrocket.com
Difference between server sent events and Websockets in HTML5 - geeksforgeeks.org
And, there are dozens of other articles here.
You may also want to be aware of socket.io which is a widely used layer built on top of webSockets that adds more features than either of these have (a named message layer, auto-reconnect, message acknowledgement, direct message response, built-in JSON support, etc...).
Any of these can do what you're asking for. Which of these to choose really depends upon the details of your requirements.
Try making a WebSocket server. There is ws package for Node.js, and alternatively socket.io. However if your client is a web client, you can use socket.io for easy-use and setup.
From: https://stackoverflow.blog/2019/12/18/websockets-for-fun-and-profit/
A WebSocket connection is meant to be persisted, so can be overkill for simpler apps.
So when we talk about socket.io which is a wrapper around websockets, we won't have to do heavy work to set up the websocket. So, why is it said that persistent connection can be an overkill for simpler apps?
If you read on, it gives an example:
A WebSocket connection is meant to be persisted, so can be overkill for simpler apps. For a one-directional news feed, metrics feed, or any app where you need to update the client but not receive information in return, Server Sent Events or plain old HTTP calls are quicker and simpler to set up.
Websockets are for when you need the server to be able to send data to the client without the client having to initiate the connection themselves first. In the examples quoted, the client can make the request just once, when the page first loads, or the server can send the data in the initial document.
socket.io can make working with sockets easier, but it still requires setting some stuff up both on the client-side and the server-side; unless you actually require a persistent connection from the server to the client, the setup and the continually open connection won't be accomplishing anything useful.
I need to send a particular header parameter in all ajax calls which is a very confidential information. I don't want from the end user to see any of the requests made in network tab of any browser. Is there any way to prevent it? or is it possible to make ajax calls directly from node server which doesn't go through browser?
Any call made on the client side cannot be hidden, as it's "client" side of the website. Even if you'd success to hide it in browser, any software could monitor it with tools such as network sniffers / monitors, WireShark for instance.
So the answer is no
When you go to a restaurent and order something, can the waiter subsequently make you forget your last instruction/order? The answer is NO, same as the answer to this question.
It all starts with client making a request to the server, hence client is the driving force of the whole interaction. Server just serves as per the instructions from client (and maliciously does some extra work on its own, say auditing, database update, cookie addition etc.).
Hence there is no way a 'server' can restrict client to see its own instructions.
Just simply don't send sensitive information directly via headers. Encrypt them via your client side code and add them within cookies or any other HTTP header(s).
Quoting from internet:
Client/server architecture is a producer/consumer computing
architecture where the server acts as the producer and the client as a
consumer. The server houses and provides high-end, computing-intensive
services to the client on demand. These services can include
application access, storage, file sharing, printer access and/or
direct access to the server’s raw computing power.
Client/server architecture works when the client computer sends a
resource or process request to the server over the network connection,
which is then processed and delivered to the client. A server computer
can manage several clients simultaneously, whereas one client can be
connected to several servers at a time, each providing a different set
of services. In its simplest form, the internet is also based on
client/server architecture where web servers serve many simultaneous
users with website data.
Never trust to client. Ever. Never ever. Doesn't matter what you do assume its been cracked. Hackers have all the tools and complete control of the client and all software running on it. Assume they've written their own network stack, their own TLS implementation, their own browser, their own operating system...
If you need to keep it secure, keep it on your servers. If you need to communicate 'privileged' information (assuming you remember that once you've sent it to a client they can access it) don't, tokenise it on your server and send them the token. And if you're generating tokens make sure they're very random and utterly opaque - don't encrypt anything in the token because you should assume they can crack that too, regardless how secure you think the library you are using is (assume it'll one day be cracked).
Never expose the confidential data on the client-side.
The best practice is to encrypt your confidential data on the server-side, send it to the client, and decrypt on the server end when the client sends you back.
If you don't want encryption or this confidential information is result of user actions itself then make a key-value pair in a database, where the key is something which can be exposed to the client (let's say username) and value is the confidential information. Hence now we have 1-1 mapping, so fetch this confidential information on server-side from database using the key we are getting from the frontend.
I hope this will help.
Good Luck!!
As we know, if running application also manage sessions in main memory then is there any way for server to send responses to all web clients/browsers for new recorded data in a database.
Remember: I have not made any request to server or polling to server for new records update..
Let server make responses without web request..
Objective :
No all web browsers making request or polling to server for every certain interval therefore reducing the performance issue with the application memory..
Am just against of making so many ajax calls from every web client..
Need your ideas from your past, if experienced similar..
read about websockets and socket.io.
basically with socket.io you have a connection open between browser (client) and server and server can send data which the client than receives as an event.
the client doesn't need to send a request to get that data, only open the web socket connection.
you can look at socket.io chat example: http://socket.io/get-started/chat/
WebSocket is the best and easy solution if you don't want to go through the hassle to learn Angular or others.
Both server-side and client-side can build WebSocket, and it acts as a bridge to transmit data back and forth.
I just created an easy solution for this.
Please check my new library wsm - WebSocket Manager, it works for both server-side and client-side.
Websocket Server can be built easily; this library includes several useful features.
I'm currently experimenting with WebSockets in a bid to reduce / remove the need for constant AJAX requests in a potentially low bandwidth environment. All devices are WebSocket compliant so there's no issue there, and I'm trying to keep it to native PHP WebSockets, no node.js or other frameworks / libraries (Which so far has been fine).
What I'm looking to do is to decide how to go about notifying connected clients about an update to a database by another Client. The use case in question is a person pressing a button on their device, which then alerts that persons manager(s) to that press. So the two options I have though of are as follows:
1. Looping a Database Query (PHP)
My first thought was to insert a query into the WebSocket server that is effectively saying "Has the alert field changed? If so, notify the manager(s)". Whilst this is the most straightforward and sensible approach (That I can think of), it seems wasteful to have a PHP script designed to reduce strain on the server, that is now running a query every second, however, at least this would ensure that when a Database update is detected, the update is sent.
2. Sending a notification from the Client
Another thought I had, was that when the client updates the Database, they could in fact send a WebSocket notification themself. This has the advantage of reducing any intensive and looped queries, but also means that I'd need to have a WebSocket message being sent every time I want to change any data, such as:
$.post("AttemptDatabaseUpdate.php", {Data}).function(Result) // Don't worry about the semantics of this, it's not actual code
{
if(Result == "Successful")
{
SendWebSocketNotification(OtherData);
}
}
Maybe this is the best option, as it is the most efficient, but I worry that there is a chance the connection may drop between updating the Database, and sending the WebSocket notification, which may create a need for a fallback check in the PHP file, much like the one in the first solution, albeit at a longer interval (Say every 30 seconds).
3. MySQL Trigger?
This is purely a guess, but perhaps another option is to create a MySQL trigger, which can somehow notify the server.php file directly? I've no idea how this would work, and would hazard a guess that this may end up with the same or similar Query requirements as solution #1, but it's just a though...
Thank you in advance for your help :)
EDIT: Solution possibility 4
Another thought has just popped into my head in fact, whereby the PHP file used to update the database could in fact have a WebSocket message built into it. So that when the PHP file updates the database, the WebSocket server is notified via PHP, is this possible?
If you use websockets, you should use notifications from client. That's one of their main use cases.
If you're worried about inconsistencies due to connection dropping or something changing in-between, you could implement a system similar to HTTP ETags, where client would send a hash code that you can respond on server side if there is a conflict in updating.
Update: I guess I understood your initial issue a bit wrong. If I understand your use case correctly: you are sending database updates from a client and after that all connected clients need to be updated. In that case, I think server should send the update messages after DB updates have been done, so I agree with solution 4. I am assuming here that your websocket server is the same server running PHP and doing the DB updates.
However, depending on your use case, client should still send a hash value on the next request identifying its "view of the world", so you would not be doing identical updates multiple times if a connection gets broken.
Update 2: so it was now understood that you indeed use a separate, standalone websocket server. Basically you have two different web servers on the server side and are having an issue on how to communicate between the two. This is a real issue, and I'd recommend only using one server at a time - either take a look at using Apache websocket support (experimental and not really recommended) or migrating your php scripts to the websocket instance.
Neither PHP or Apache was really build with websockets in mind. It is quite easy to set up a standalone websocket server using only PHP, but it might not be so easy then to migrate the rest of the PHP stack to it if the code is relying on Apache/web server on. Apache websocket support also is hardly optimal. For a real websocket solution, unfortunately, best practice would be using a technology that is built for it from the ground up.
The better answer is to send notification through Server side when database is updated by PHP script, so that script have to add options of web sockets to directly send notification to all web socket clients registered.
User send content->Php script process content and save data according to true condition->check database is updated by checking return of mysql_query/other alternative->if true than use web-socket and send notification to all users
now this is more easy/handy/bandwidth saver.