How to receive the result after sending data via WebSocket - node.js

Using ws package from npm you can do something like that:
const ws = new WebSocket('ws://localhost:9003');
ws.on('open', () => ws.send('rcon_password PASSWORD'));
ws.on('message', result => console.log(result));
If server expects client to send password then returns authentication result, how can i check result sent by server?
In Python you could do something like:
async with websockets.connect('ws://localhost:9003') as websocket:
await websocket.send('rcon_password PASSWORD')
result = await websocket.recv()
Client can send other commands later. How to relate data sent with ws.send() with those sent to another function in the event onmessage?

The webSocket protocol itself has no concept of a response to a message you send. And, because Javascript is event driven, you can't just block waiting for the response). So, the server just needs to send a message back to the client and the client needs to have a handler for incoming messages and handle the response appropriately when it arrives. If you need to make sure it's a response to THE specific message you previously sent to the server, then you can include some sort of messageID (that you coin yourself) when you send the first message and include that same messageID in the server response.
If you step up to the socket.io library for both client and server (which runs on top of the webSocket transport), then it has built-into it the concept of a response to your message. When sending your message, you just register a callback that gets called when the response comes back and the server has to handle its side appropriately to trigger the response callback on the client.

Related

Is there good standard way to simulate Req/Res over Websocket?

I'm building my app entirely over websocket. While I see benefit of being able to send data to client without having client to request data to me. There are still benefits to req/res type of interaction as you can put all logic together.
Ex:
Take registration. You send data, server sends a OK or ERROR if something is wrong.
Right there it's three events! DataFromClient, RegistrationFailed, RegistrationSuccess. But with REST I could have made one POST request and handle if else in one function.
It shouldn't be too hard to create a library that allows you do to push notification + Req/Res type of interaction. It'd be even better if routes could be defined like express routes.
There is no "standard" way to implement request/response with webSocket. It is not part of the webSocket standard. It can certainly be done (more below on this), but there is no "standard" way of doing it.
The socket.io library which is built on top of webSocket has a response option built into any message it sends.
The sender does something like this:
socket.emit("msgName", someData, function(data) {
// data is the "response" to sending this message
console.log(data);
});
The recipient of a message that is expecting a response does something like this to cause the response to be sent:
socket.on("msgName", (someData, fn) => {
// send response
fn(someOtherData);
});
You could implement your own response scheme in webSocket. You'd have to add to your data format a uniqueID for each request so you could send that same uniqueID back in the response so the receiver would know which response belongs with which request.

Using Socket.io with Sequelize

I am trying to use Socket.io and Sequelize to create a chat app. Socket.io will handle the socket to allow for instant messaging. Sequelize will handle storing the messages so when you refresh the screen you still have your messages.
What is happening is that on localhost my socket works, but it does not send the messages to the database. When I put it onto Heroku, my database worked, but it does not use the sockets.
My socket is located in app.js and my database route is located in routes/messages.js.
I have been working on this bug for a while now and I have been trying to get help with it. I think the best way to share this is with my markdown I created detailing my efforts to fix my bug that can be found at here. My repo for this can be found here.
There are a few different parts that you need to distinguish:
the HTTP server, in your code represented by the variable http
the Express app, represented by app
the Socket.IO server, represented by io
a Socket.IO (client) connection (see below)
The HTTP server directs "normal" HTTP requests to the Express app, which will handle them according to the middleware and routes that are set up. A router handler gets called with (at least) two arguments, generally called req and res, to represent the (incoming) HTTP request and the (outgoing) HTTP response.
The Socket.IO server gets to handle specific Socket.IO requests, which get sent to the server by the Socket.IO client (running in the browser). When such a client sets up a connection with the server, the connection event gets triggered on the server. Any handlers for this event will get passed an argument, generally called socket, that represents the (bidirectional) connection with that client.
That Socket.IO connection can receive messages (sent from the client running in the browser), which trigger events on the socket. You can install a handler to listen for particular messages (like "chat message"), which will receive, as argument, the data that was sent to it by the client.
The issue in your code seems to be with setting up everything to handle those chat messages. The correct setup order would be:
listen on the Socket.IO server for connection events
when such an event is received, add a listener for the chat message event on the connection
when such an event is received, write the data to the database.
In code:
// Listen for new client connections.
io.on('connection', function(socket) {
// Listen for the client to send a _"chat message"_ message.
socket.on('chat message', function(data) {
// Store the data in the database.
models.Messages.create({
message : data.message,
username : data.username
});
});
});
As you can see, req and res aren't available inside of those Socket.IO event handlers, because those are only used for normal HTTP requests.
Also, as opposed to HTTP, you don't necessarily have to send anything back to the client when you have received a message, so I left that part out. The handler above only writes the message data to the database (it also doesn't check for, or handle, errors, which eventually you should add).

Socket.io : How to handle/manage multiple clients requests and responses?

I am very eager to integrate Socket.io to my node.js project, but I have some confusions on how to properly use socket.io. I have been looking through documentations and tutorials, but I have not been able to understand some concepts on how socket.io works.
The scenario I have in mind is the following:
There are multiple clients C1, C2, ..., Cn
Clients emit request to the server R1,...,Rn
Server receives request, does data processing
When data-processing is complete, Server emits response to clients Rs1, .., Rs2
The confusion I have in this scenario is that, when the server has finished data processing it emits the response in the following way:
// server listens for request from client
socket.on('request_from_client', function(data){
// user data and request_type is stored in the data variable
var user = data.user.id
var action = data.action
// server does data processing
do_some_action(..., function(rData){
// when the processing is completed, the response data is emitted as a response_event
// The problem is here, how to make sure that the response data goes to the right client
socket.emit('response_to_client', rData)
})
})
But here I have NOT defined which client I am sending the response to!
How does socket.io handle this ?
How does socket.io make sure that: response Rs1 is sent to C1 ?
What is making sure that: response Rs1 is not sent to C2 ?
I hope I have well explained my doubts.
The instance of the socket object corresponds to a client connection. So every message you emit from that instance is send to the client that opened that socket connection. Remember that upon the connection event you get (through the onDone callback) the socket connection object. This event triggers everytime a client connects to the socket.io server.
If you want to send a message to all clients you can use
io.sockets.emit("message-to-all-clients")
and if you want to send an event to every client apart the one that emits the event
socket.broadcast.emit("message-to-all-other-clients");

Edit message in socket.io before it is sent to the user

I'd like to intercept certain messages being sent in the receiver point of view. This means, for example:
SENDER SIDE
User sends message
Server receives message
Message could be treated here but I don't want to work it here
RECEIVER SIDE
I want to treat it in the server before being emit
Message is emit
User receives message (for example, in browser) with socket.on('message',(...));
Does anyone have any idea which part of the code needs to be changed in socket.io to accomplish that? I've been searching the modules: adapter, client, parser... but found nothing relevant... Any thoughts on this one? I've been getting a bit desperate xp
server side:
socket.on("chat", clientMsg);
function clientMsg(data){
console.log("data received:" + data)
var msg = data; // set the msg to be sent
// treat the data server side or
// if wanting to treat the data from the user's side
// create another socket.on() inside this function. to treat it remotely (if needed)
// then, when finished send the message to all users with the treated data.
io.sockets.emit("chat", msg)
};

Connecting to a Reliable Webservice with Nodejs

My application needs to receive a result from Reliable Webservice. Here is the scenario:-
First I send a CreateSequence request. Then the server replies with a CreateSequenceResponse message. Next I send the actual request to the webservice.
Then the webservice send a response with 202 accept code and sends result in a later message. All these messages contain the header Connection: keep-alive.
I made request with http.ClientRequest. I could capture all responses except the result. http.ClientRequest fires only one response event.
How can I receive the message which contains the result?
Is there any way to listen to socket for remaining data (socket.on('data') did not work). I checked this with ReliableStockQuoteService shipped with Apache Synapse. I appreciate if someone can help me.
When you get the response event, you are given a single argument, which is an http.IncomingMessage, which is a Readable stream. This means that you should bind your application logic on the data event of the response object, not on the request itself.
req.on('response', function (res) {
res.on('data', console.log);
});
Edit: Here is a good article on how to make HTTP requests using Node.

Resources