2

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.

Community
  • 1
  • 1
Marcus
  • 512
  • 1
  • 7
  • 22
  • 3
    I believe that you are referring to web sockets. Read up on socket.io and then try it out yourself. It's pretty straight forward. – KJ Price Mar 09 '15 at 21:49
  • @KJPrice I use Socket.io in my actual project, my client is written in HTML and I am able to call JavaScript functions through my C# Application to send messages to the Server, that part is straight forward, I haven't however been able to do the same from Server to Client – Marcus Mar 09 '15 at 22:02
  • I guess this is similar to what you were looking for: [url](http://stackoverflow.com/questions/4647348/send-message-to-specific-client-with-socket-io-and-node-js?lq=1). Did you take a look ? – Arnaud Bertrand Mar 09 '15 at 22:09
  • @ArnaudBertrand Yes I did, but as I mentioned actually sending a message isn't the problem, I want to be able to call a function in the server.js file, pass in a parameter and then send that message from Server to Client. This should only happen when the function is called – Marcus Mar 09 '15 at 22:15
  • By taking the same variables as the example in the page if you do ioClient.emit('nameyouwant',variable) you can call a function in your server side by doing on your server socket.on('nameyouwant', function(var){}). This is client -> server. If this it what you are looking for I can make it more clear in an answer. – Arnaud Bertrand Mar 09 '15 at 22:31
  • @ArnaudBertrand the problem with this is that it requires the client to send a message first and practically request the server to send it's message. My server has a GUI with a start and stop button, it should also have a button that calls a function in its JavaScript that causes the message to be sent. Which is why I'm looking for a way to call a Server side function without going through the client as you suggested – Marcus Mar 09 '15 at 22:36
  • Did you have a try by making your socket variable global ? – Arnaud Bertrand Mar 09 '15 at 22:43

3 Answers3

5

The best way to send messages from server to client right now is using webSockets. The basic concept is this:

  1. Client A loads web page from server B.
  2. Client A runs some javascript that creates a webSocket connection to server B.
  3. Server B accepts that webSocket connection and the socket stays open for the duration of the life of the web page.
  4. Server B registers event handlers to handle incoming messages from the web page.
  5. Client A registers event handlers to handle incoming messages from the server.
  6. At any point in time, the server can proactively send data to the client page and it will receive that data.
  7. 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.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • This cooperation between client and server is what I'm after. My application is simply a program written in c# that spawns a process that runs the node server. The client essentially controls a moving object in the C# application, when this object reaches some location marker, I want the c# application to tell the server to emit a message. This is why I am after a solution that allows me to emit messages after the server has started. This would be easily done by calling a JavaScript function through HTML on the client webpage but how can this be achieved on the Server – Marcus Mar 10 '15 at 01:29
  • @Marcus - a challenge with this question is that you never really described the whole problem. Are you asking how a C# application can notify the node.js application to send a webSocket message to the client? Is that the question? Because I've fully described how the node.js server would send a message to the client already. So, is the remaining part of the question how the C# application would communicate with an already runniong node.js server to tell it to notify the client? If so, then I'd suggest a simple Ajax call (e.g. http request) from C# to the node.js server. – jfriend00 Mar 10 '15 at 01:35
  • I agree. As I have already successfully implemented the client and can call JavaScript functions to send messages to the Server I posed my question with this in mind, which is why I asked for a way to trigger a function call after the Server had started. I felt the c# part was not necessary to add as I could've implemented that if the triggering a function call was possible, I see the confusion and I acknowledge your description of inter message transmission. I will look into the Ajax calling you described. – Marcus Mar 10 '15 at 02:05
2

In order to send a command to a client via the console there are two options, single process or multiprocess:

Single Process

  1. When the command is run from console, temporary socket.io server starts listening on a port.
  2. Once the client connects, send the message to the client.
  3. 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:

  1. Spin up a stand-alone server that connects with clients.
  2. Create a very similar console node app that will send a message to the server to forward on to clients.
  3. 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).
Community
  • 1
  • 1
Jim Buck
  • 2,383
  • 23
  • 42
  • Thank you, I have been able to make a client in the Server as described. My problem is that; I have a c# application that starts the node server in the background when a button is clicked. A client controls an object, say a car in the c# application, when this car gets to a certain location, I expect the server to tell the client that the car is there. I see how this could work with the first approach but as you said its not very efficient. How would this work with the second, how can I emit a message after the server has already started – Marcus Mar 10 '15 at 01:23
  • I'm slightly confused because you call both the C# App and the Browser Client "client". Just call them `server`, `client`(browser), and `app` (C#). I have updated my answer with further examples. If you need more detail I will expand at your request. – Jim Buck Mar 10 '15 at 03:16
  • Thanks, I have been looking into Edge.js and it seems promising, except that I can't get it to work with Windows Forms yet. Your third suggestion is the route I am currently taking, which is what spawned my question. Since the node server is started in a process Im not able to pass information to the server after its started to be broadcast to a client. Please refer to [this question](http://stackoverflow.com/questions/28974713/get-socket-io-client-working-in-c-sharp-webbrowser) for more details – Marcus Mar 11 '15 at 17:50
  • I'll have a working example soon for you soon. Should be on GitHub sometime tomorrow (I'll post a link). – Jim Buck Mar 13 '15 at 00:35
0

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 });
            }

    }
Dslayer
  • 1,101
  • 14
  • 17
  • Using `cURL` would be pretty cool, just make sure you protect it from outside attacks. Security would be very important. – Jim Buck Mar 10 '15 at 00:13
  • yeah that's the idea. these functions have lots more, just cutted off the parts that aren't addressing the subject for clarity. – Dslayer Mar 11 '15 at 00:53