I have a node.js server which is communicating from a net socket to python socket. When the user sends an asynchronous ajax request with the data, the node server passes it to the python and gets data back to the server and from there to the client.
The problem occurs when the user sends the ajax request: he has to wait for the response and if the python process takes too much time then the ajax is already timed out.
I tried to create a socket server in node.js and a client that connects to the socket server in python with the data to process. The node server responds to the client with a loading screen. When the data is processed the python socket client connects to the node.js socket server and passes the processed data. However the client can not request the processed data because he doesn't know when it's done.
So you have three systems, and an asynchronous request. I solved a problem like this recently using PHP and the box.com API. PHP doesn't allow keeping a connection open indefinitely so I had a similar problem.
To solve the problem, I would use a recursive request. It's not 'real-time' but that is unlikely to matter.
How this works:
The client browser sends the "Get my download thing" request to the Node.js server. The Node.js server returns a unique request id to the client browser.
The client browser starts a 10 second poll, using the unique request id to see if anything has changed. Currently, the answer is no.
The Node.js server receives this and sends a "Go get his download thing" request to the Python server. (The client browser is still polling every 10 seconds, the answer is still no)
The python server actually goes and gets his download thing, sticks it in a place, creates a URL and returns that to the Node.js server. (The client browser is still polling every 10 seconds, the answer is still no)
The Node.js server receives a message back from the Python server with the URL to the thing. It stores the URL against the request id it started with. At this point, its state changes to "Yes, I have your download thing, and here it is! - URL).
The client browser receives the lovely data packet with its URL, stops polling now, and skips happily away into the sunset. (or similar more appropriate digital response).
Hope this helps to give you a rough idea of how you might solve this problem without depending on push technology. Consider tweaking your poll interval (I suggested 10 seconds to start) depending on how long the download takes. You could even get tricky, wait 30 seconds, and then poll every 2 seconds. Fine tune it to your problem.
Related
I'm trying to understand the event loop in Node JS. There are fantastic resources online but i keep finding myself wondering the same thing. The scenario is below:
For Javascript/Node
On a web page with a getData button.
The user clicks the button and a request is sent to the server to the getData route (in this simplified scenario when the server gets the data it returns a new page showing the data). The data request is asynchronously offloaded to a Node API (and out of the call stack).
Before the api returns the data the user changes pages in the browser, a new http request is sent to the server for a different page and this fires an http.get(url, callback) adding the new page to the callback queue to be loaded (this beats the data request and the new page is returned).
What happens to the old callback for the now redundant data? Presumably when the event loop reaches the getData callback in the cb queue, it will attempt to run the callback function. Will Node send a response to change the page again with the data displaying page? If it was Ajax and the data returned after a page change what happens to the callback in this scenario, does ajax simply ignore the returned data on the new, different page?
I know Ajax handles on page updates but i wanted to simplify to understand how the event loop handles situation where the call stack has moved on and the older callbacks are no longer useful.
Thankyou for the responses they have been very useful! The only thing that i would add is (and i understand this scenario requires very bad server design but the theory is my interest here) if the server does respond with a page that is no longer wanted by the user (due to the delay in async response), does the browser understand that this is not the most recent request? I think as http is stateless the browser will receive the response over TCP and reload with the previously requested page (to the the clients frustration).
Many thanks!
Pretty sure the browser discards the response because the request itself is closed. It depends on the timing, the server (forget whether it's node.js or apache or anything else) might still get the response in time to try to respond to it. If it does respond to it, it doesn't care what the browser does with the response.
You say
The user clicks the button and a request is sent to the server to the getData route (in this simplified scenario when the server gets the data it returns a new page showing the data). The data request is asynchronously offloaded to a Node API (and out of the call stack)
The browser is oblivious of the server's implementation. It doesn't care how the server responds as long as it tries to respond. At the same time, the server is also oblivious of the "state" of the browser. All the server knows is that there is an open request that it needs to respond to and does so. Once it has responded, it doesn't care.
I know Ajax handles on page updates but i wanted to simplify to understand how the event loop handles situation where the call stack has moved on and the older callbacks are no longer useful.
There is no movement of the callstack, the server received a request and as long as that request is open, the server should respond to it. If another request comes in (even if the new request is nearly identical) the server will also respond to that request separately.
In a simplified HTTP request scenario, a connection is established between client (eg Web browser) and server first, using TCP.
HTTP is sent over this link to configure the exchange of data.
The TCP connection is maintained until either end closes it (usually client says "Thanks! All done!"). So the TCP connection remains open while the Node.js process fetches some data asynchronously.
If a user gives up waiting for a response and (say) closes the browser, then the TCP connection is closed on both ends. Meanwhile, the callback for the database call continues to exist in server memory, ready for when the DB returns. The DB then returns, the callback is run, and as soon as the callback attempts to send data back to the client over the TCP connection it will discover it has been closed and a suitable error will be raised (and possibly caught) on the server-side.
The callback then exits, the stack frame is popped off the stack, the memory allocated to the stack frame is freed, and control returns to the previous frame. When the garbage collector in the Node.js JavaScript runtime next runs, any objects solely linked to that no-longer-in-existence frame are swept up and the memory associated with them is freed.
In an unhappy-path scenario (eg. power plug pulled on the client computer), then the server will think the TCP connection is still open for a configurable period, until it times out, or it discovers it is unable to successfully send data across it, at which point the server closes it and cleans up the associated memory.
This can be complicated by the concept of HTTP keep-alive, which involves the browser and server agreeing to use a single TCP connection for multiple HTTP requests to save time. Under HTTP keep-alive, the HTTP protocol is leveraged to ensure the browser will safely ignore any data returned over the TCP connection that corresponds to a no-longer active request.
And there is an even more modern technique of multiplexing several concurrent HTTP requests over the same TCP connection too, but that is outside the scope of this question.
I think.
I want to send messages from my server to my client when a function is called. Using the code from this answer messages can be successfully sent from Server to Client every second.
I am building an application that runs node in the background, ideally I would like to be able to click a button that will call a function in the node server.js file which takes a parameter and sends that message to the client. The function in question would look like this
function sendToClient(message) {
clients[0].emit('foo', msg);
}
This would send the passed in message to the first client. How can I go about this?
In terminal, after you run node server.js is there a way to call a function from the server file using terminal, this could be a possible solution if so.
The best way to send messages from server to client right now is using webSockets. The basic concept is this:
Client A loads web page from server B.
Client A runs some javascript that creates a webSocket connection to server B.
Server B accepts that webSocket connection and the socket stays open for the duration of the life of the web page.
Server B registers event handlers to handle incoming messages from the web page.
Client A registers event handlers to handle incoming messages from the server.
At any point in time, the server can proactively send data to the client page and it will receive that data.
At any point in time, the client may sent data to the server and it will receive that data.
A popular node.js library that makes webSocket support pretty easy is socket.io. It has both client and server support so you can use the same library for both ends of the connection. The socket.io library supports the .emit() method mentioned in your question for sending a message over an active webSocket connection.
You don't directly call functions from client to server. Instead, you send a message that triggers the server to run some particular code or vice versa. This is cooperative programming where the remote end has to be coded to support what you're asking it to do so you can send it a message and some optional data to go with the message and then it can receive that message and data and execute some code with that.
So, suppose you wanted the server to tell the client anytime a temperature changed so that the client could display in their web page the updated temperature (I actually have a Raspberry Pi node.js server that does exactly this). In this case, the client web page establishes a webSocket connection to the server when the page loads. Meanwhile, the server has its own process that is monitoring temperature changes. When it sees that the temperature has changed some meaningful amount, it sends a temperature change message to each connected client with the new temperature data. The client receives that message and data and then uses that to update it's UI to show the new temperature value.
The transaction could go the other way too. The client could have a matrix of information that it wants the server to carry out some complicated calculation on. It would send a message to the server with the type of calculation indicated in the message type and then send the matrix as the data for the message. The server would receive that message, see that this is a request to do a particular type of calculation on some data, it would then call the appropriate server-side function and pass it the client data. When the result was finished on the server, it would send a message back to the client with the result. The client would receive that result and then do whatever it needed to with the calculated result.
Note, if the transactions are only from client to server with a response then coming back from the server, a webSocket is not needed for that type of transaction. That can be done with just an Ajax call. Client makes ajax call to the server, server formulates a response and returns the response. Where webSockets are most uniquely useful is if you want to initiate the communication from the server and send unsolicited data to the client at a time that the server decides. For that, you need some continuous connection between client and server which is what a webSocket is designed to be.
It appears there may be more to your question about how to communicate from a C# server to your node.js server so it can then notify the client. If this is the case, then since the node.js server is already a web server, I'd just add a route to the node.js server so you can simply do an http request from the C# server to the node.js server to pass some data to the node.js server which it can then use to notify the appropriate client via the above-described webSocket connection. Depending upon your security needs, you may want to implement some level of security so that the http request can only be sent locally from your C# server, not from the outside world to your node.js server.
In order to send a command to a client via the console there are two options, single process or multiprocess:
Single Process
When the command is run from console, temporary socket.io server starts listening on a port.
Once the client connects, send the message to the client.
Disconnect and stop the console app.
The reason this works is that socket.io clients are always trying to connect to the server. As long as the browser is open, they will try to connect. So even if the server only comes on for a few seconds, it should connect and receive messages. If the client is not running then simply create a timeout that will stop the console app and inform the user that it failed to broadcast the command.
While this approach is very easy, it's not robust nor efficient. For small projects this would work, but you'll have better luck with the next approach:
Multi-Process
This approach is much more reliable, expandable, and just better looking when you are talking about architecture. Here's the basic summary:
Spin up a stand-alone server that connects with clients.
Create a very similar console node app that will send a message to the server to forward on to clients.
Console app completes but the main server stays up and running.
This technique is just interprocess communication. Luckily you already have Socket.IO on the primary server, so your console app just needs to be another socket.io client. Check out this answer on how to implement that.
The downside to this is that you must secure that socket communication. Maybe you can enforce it to just allow localhost connections, that way you need access to the server to send the run command message (you absolutely don't want web clients executing code on other web clients).
Overall it comes down to the needs of your project. If this is a quick little experiment you want to try out, then just do it single process. But if will be hosting an express server (other webservers are available) and need to be running anyways, then multi-process is the way to go!
Example
I've created a simple example of this process using only Socket.io. Instructions to run it all are in the readme.
Implementations
In order to have C# (app) -> Node.js (server) -> Browser (client) communication then I would do one of the following:
Use redis as a message queue (add items to the queue with the app, consume with the server, which sends commands to client).
Live on the wild side and merge your NodeJS and C# runtimes with Edge.js. If you can run NodeJS from C# you will be able to send messages from your app to the server (messages are then handled by the server, just like any other socket.io client-server model).
Easier, but still kinda hacky, use System.Diagnostics.Process to start a console tool explained in the Multi-Process section. This would simply run the process with arbitrary parameters. Not very robust but worth considering, simple means harder to break (And again, messages are then handled by the server, just like any other socket.io client-server model).
I would create a route for sending the message and send message from post parameter. From CLI you can use curl or from anywhere really:
app.get('/create', function(req, res) {
if( data.type && data.content && data.listeners){
notify( data );
}
});
var notify = function( notification ){
ns_mynamespace.in(notification.listeners.users)
.emit("notification", {
id: notification.id,
title: 'hello', text: notification.content });
}
}
I notice an instant messenger using javascript/http/xmlhttprequest rather than tcp/websocket to communicate.
such as http://w.qq.com/login.html
I monitored its communication way in chrome developer tool.
All are http requests. One request to server every minute.
The thing I confused is that if I send a message to the http client, it receives the message immediately.
As I know http client can not get message from others, it has to send request and get response.
Is there any way to make http client to get message from others without using tcp/socket or sending request and geting response?
Your comment welcome
I don't get all this asian hieroglyphs, but they probably use long-polling: client asks server for new data and server holds answer (don't send anything, and don't close connection) while data is not ready (new message came) or until huge timeout expired. As soon as connection closed, client process response and sends next long poll request. The more common term for "permanent" connect via http called Comet. As you can see, Comet can be implemented via many techniques. As for me, the most modern is ajax streaming. It requires modern browser of course, but worth it. It's not so hard to implement streaming by yourself, but I believe there are few js libs which do the job for you.
Upd:
Here is pretty good explanation with code source
and
here is one of many questions about streaming on SO (the answer in the bottom is most interesting I guess)
I'm pretty new to web development, so excuse my ignorance.
What I'd like to know is if there's a way to have the server broadcast a message to clients. An example of this would be a client page that has a newsfeed, and every time a new story comes in to the server, the server sends that information out to the client and the client updates its page's newsfeed. I don't want the client to constantly be polling the server every few seconds, asking "hey, is there a new story now? what about now? what about now???" I want the client to be doing its own thing, and then be interrupted by a message from the server.
Is there a way to do this?
For newer browsers, you can use web sockets to open a continuous connection to a server and then client/server can send each other messages whenever they want.
For older browsers, the way this is typically done is that the client has to "poll" the server to ask the server on some regular schedule if the server has any new messages for it. The server usually cannot connect directly to the client because of firewalls, local security settings, unknown location, etc... so the client has to connect to the server. Polling can either be of the regular variety, poll every 60 seconds with an ajax call to ask if there's anything new or it can be more of a long poll where the client asks if there is something new and, if there is something new, the server returns right away with that data. But, there's nothing new, the server hangs onto the polling request for some time period waiting to see if there is something new. Eventually, the server will either return that it has nothing or return with a new message if there is one. When the client gets the response, it starts the "long poll" sequence over again. Comet is an example of the "long poll" in a library form that makes it easier to implement.
Pusher is tailor-made
http://pusher.com/
I wanted to create a web chat. It was suggested that i use Php Socket Servers. I've made one and they function well with a telnet client.
What i find myself bamboozled by is how to get that data to the client via ajax (no page refreshes).
All I can come up with is calling a php file with ajax, getting the data and updating the page. But that will not work the other way around.
Or am i missing something?
How would you implement a 1 on 1 web chat?
One solution is long-polling. The client will open up an AJAX request to a script that will block and wait for data to come in. If no data comes in within a minute, it will return and the client will reopen the connection. If data comes in, then it will immediately return the data and the client will update its view.
For sending the data, just do a normal AJAX callback.
You've got the idea of client-initiated communication, which is fine for sending things from the client to the server.
As a consequence of the stateless nature of HTTP, there is no way to "push" data, unbidden, to the client.
The way you get around this is by always leaving a connection back to the server open. The request is pending, and when the server has something to say, it responds to the pending request. Whenever this happens, the client creates a new request to leave sitting until the next time server->client communication must happen.
Another way to implement near-real-time communication is through frequent polling. But I don't recommend this approach, really. Especially not for a chat program.