How to resolve React.js socket.io acknoweldgement timed out? - javascript

I have a Node.js and React.js applications, server and client, respectively. I send data between them via socket.io and I am trying to implement acknoledgement but I get an error saying its been timed out:
Error: operation has timed out
at Timeout._onTimeout (C:\Project\gateway\node_modules\socket.io\dist\broadcast-operator.js:137:30)
at listOnTimeout (node:internal/timers:559:17)
at processTimers (node:internal/timers:502:7)
Here is my server code. Here the message variable prints Error: operation has timed out
socket.emit((topic, message),function(message) {
console.log('GOT MESSAGE');
console.log(message);
});
Here is my client code:
ioClient.on('triton/acs', (data, callback) => {
callback("Message for server")
}
Whhy is this not working and how to fix it?

As #darvine mentioned, there is not a lot of code to see how you implement socket.io server side and client side. However, from what I see above, I'm trying my best to answer your question in broad strokes since I am seeing a few syntax errors.
Your backend code:
socket.emit((topic, message),function(message) {
console.log('GOT MESSAGE');
console.log(message);
});
It appears that you did not establish a connection to the client. You would achieve that by doing the following. Also, socket.emit is sending the data to the client. (There is no callback function in .emit). You send the data as the second parameter. If you want to receive data from the client then you use .on('listener', cb). See below;
//establish connection to the client
io.on('connection', (socket)=> {
//sending a message to the client
socket.emit('yourSentMessage', 'you are sending this message to the client');
//receiving a message from the client.
socket.on('yourReceivedMessage', (msg) => {
console.log(msg) //this message was received from the client
});
});
On the frontend, it is important that you provide your socket instance appropriately. I would utilize context api. See this article for further information on this. You can wrap the components in the provider and have access to the socket instance. Again, it is also important to destinguish between .emit and .on on the frontend. If you want to send data to the backend, you utilize .emit (no callback). If you receive data from the backend, you utilize .on('listener', cb).
Lastly, react requires you to set the proxy server while you are running on localhost. You do that in the package.json file as shown in the screenshot below:

Related

How to send a message with WebSocket to a Socket.io server

I'm developing a React Native application and I want to use the WebSocket class to communicate with my Socket.io server.
I can connect to the server just fine, but I'm having problems sending messages to it using the .send() method.
I tried this on React Native:
var socket = new WebSocket("ws://host:port/socket.io/?transport=websocket");
socket.onopen = () => {
console.log("connected");
socket.send('data');
};
On my Socket.io server I have this listener that I created just for testing:
socket.on('data', function(data) {
console.log("data");
})
The connection does work, and I'm able to see that on the server too. But when I do socket.send('data') the disconnect event gets called on the server rather than the data event I wrote above. (I tested this by using a function to call the .send() method, so this does cause a disconnect on the server)
Can anyone shine some light on this?
That's because Socket.io is not exactly compatible with WebSocket - there are initial handshakes, connection fallbacks (eg. when no WS is available, use AJAX long pooling or other technique) and other things that Socket.io hides from you to make your life easier. Essentially, Socket.io should be seen as a separate protocol.
To connect to a Socket.io server, you have to use Socket.io client library.
ws.send(`42${ JSON.stringify(["message", { command: "register" }] }`), err => {
if (err) console.log("err", err);
});
This code using the ws pacakge as the example.
You need to add the 42 to tell socoket.io server that you are sending message, the {command: "register"} is the data you send, the "message" is the channel that socket.io is listening on.
io.on("message", (data) => {
console.log(data); // => {command: "register"}
});
Explain: this is the engine.io-protocol that socket.io is using. Check it's spec.
The best solution is using socket.io on both side or don't use socket.io at all.

Can client know Node.js server has disconnected him

Environment
Server: Node.js
Client: Browser
Communication: Socket.io
I already handle on server side when a client disconnects. But I wonder, is it possible to handle a server disconnection on client side?
Said in other words,
suppose server enters exception state and shuts down, how can the client know this happened? Can I use the very same code
socket.on('disconnect', function() {...});
on client?
Appreciate the help.
Things tried
To check if client is getting notified via
socket.on('disconnect', function() {...});
I throw the following exception in the server:
setTimeout(function () {
console.log('Throwing error now.');
throw new Error('User generated fault.');
}, 9000);
In client I have:
socket.on('disconnect',function(data){ console.log('Server disconnected you'); } );
But the log message in client never happens. ¿?
From the socket.io client docs:
Events
connect. Fired upon connecting.
disconnect. Fired upon a disconnection.
So yes, the client works in identical manner to the server.
Checkout other socket.io client-side events. https://github.com/Automattic/socket.io/wiki/exposed-events
Try to listen 'reconnect_failed' or 'error' instead of 'disconnect'.

Error while getting messges from sockets in javascript

Hi i am having trouble with creating a socket communication from java script code.
I am always getting error while sending a message or closing the socket from server.
My Socket server code.
// Start listening for connections.
while (true)
{
Console.WriteLine("Waiting for a connection...");
// Program is suspended while waiting for an incoming connection.
Socket handler = listener.Accept();
data = null;
// An incoming connection needs to be processed.
while (true)
{
int bytesRec = handler.Receive(bytes);
data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
break;
}
// Show the data on the console.
Console.WriteLine("Text received : {0}", data);
// Echo the data back to the client.
byte[] msg = Encoding.ASCII.GetBytes(data);
handler.Send(msg);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
JavaScript code:
var connection = new WebSocket('ws://Myip:11000', ['soap', 'xmpp']);
// When the connection is open, send some data to the server
connection.onopen = function () {
connection.send('Ping'); // Send the message 'Ping' to the server
connection.send('your message');
};
// Log errors
connection.onerror = function (error) {
console.log('WebSocket Error ' + error);
};
connection.onclose = function (msg) {
console.log('WebSocket Error ' + msg);
};
It gets connected to server socket, but always gets error while closing or sending a message from server.
If this is really your actual code:
handler.Send(msg);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
…then it's pretty broken. First, you can't assume that Socket.Send() actually sends all the bytes you asked it to. You have to check the return value, and keep sending until you've actually sent all the data.
Second, the initiation of a graceful closure should use SocketShutdown.Send, not SocketShutdown.Both. Specifying "Both" means (among other things) that you're not going to wait for the other end to negotiate the graceful closure. That you're just done and won't even receive any more data, in addition to being done sending.
And of course, the code is calling Close() before the other end has in fact acknowledged the graceful closure (by itself sending any remaining data it wanted to send and then shutting down with "Both").
Is all this the reason for your problem? I can't say for sure, since I have no way to test your actual code. But it's certainly a reasonable guess. If you tear down the connection without waiting after you try to send something, there's not any guarantee that the data will ever leave your machine, and in any case the other end could easily see the connection reset before it gets a chance to process any data that was sent to it.
There aren't a huge number of rules when it comes to socket programming, but what rules exist are there for a reason and are generally really important to follow. You should make sure your code is following all the rules.
(The rest of the code is also different from what I'd consider the right way to do things, but the problems aren't entirely fatal, the way that the over-eager connection destruction is).
I am afraid WebSocket does not work that way.
When the Javascript code connects to the server, it will send a HTTP request as ASCII text. That request will include a HTTP header Sec-WebSocket-Protocol: soap, xmpp, as you are requiring those protocols in your WebSocket creation.
Since your server code does not reply with an appropiate HTTP response accepting the websocket connection, the connection will fail. When you try to send data back, the client will not recognize it as a HTTP response and a error will be thrown.
A websocket is not a regular socket connection, it won't work that way. It requires HTTP negotiation and there is a schema for data framing. I recommend you to go through this article that explains very well how it works: http://chimera.labs.oreilly.com/books/1230000000545/ch17.html
If you are interested in learning how to develop a server, take a look to this tutorial in MDN: https://developer.mozilla.org/en-US/docs/WebSockets/Writing_WebSocket_server I also have an open source WebSocket server in C# you can take a look if you like.

Establishing WebSocket Connection within and for a JS API

Aim: In order to provide a simple, easy-to-use JS library that communicates with a server I am trying to establish a WebSocket connection at the start of my API and define the library's functionality thereafter.
Problem: The issue is that my socket's readystate does not transition to 1 (ready) before the library is loaded and the user's script is run. Debugging this has confirmed this and I'm not sure how to ensure my WebSocket is established before proceeding with the user's script.
What I have:
(function(myObject) {
var socket = new WebSocket(url);
socket.emit = function() {
//do some tasks and create a var "message"
socket.send(message);
}
window.myObject = myObject.prototype = {
doSomething: function() {
socket.emit();
}
}
}(myObject = window.myObject || {}));
Above, I've defined a custom method (socket.emit()) on the socket object that, in turn, calls socket.send(). I do this to manipulate some data before sending it via socket.send(), reusing code that would otherwise be repeated.
Then I have some very basic html that includes this JS library and a simple script runs as follows:
$(document).ready(function() {
myObject.doSomething();
});
The error I get is: "Failed to execute 'send' on 'Websocket': already in CONNECTING state."
The library successfully loads but the Websocket does not complete connection before the client script is run. How can I ensure my WebSocket is connected (readystate == 1) before the API finishes loading?
Thanks for the help!
What you could do is buffer all messages in socket.emit as long as the socket is not connected and send them once you receive the onOpen callback.
While this will handle your current problem you will see that new ones will arise:
You might want to handle disconnects from your server and reconnects and therefore you might need to extend your library API anyhow to also expose connectionstate change events and force the library user to only send messages when connected.

socket.io in node.js: socket.emit doesn't complete before socket.disconnect

I'm trying to use node.js as a server with socket.io (over a https connection server object, client connecting with option secure: true) with a JavaScript front end.
On the server if a login attempt fails I am calling:
socket.emit('unauthorized');
socket.disconnect();
On the client side I have:
this.Socket = io.connect(server, { secure: true });
this.Socket.on('disconnect', this.Socket_Disconnect);
this.Socket.on('unauthorized', this.Socket_Unauthorized);
I am able to see the disconnect event firing (with arguments set as ['booted'] regardless of whether i pass any arguments to socket.disconnect(), but the unauthorized event never makes it. Am I attempting to pass this message the wrong way?
The rationale I have here is that I want to be able to send different types of disconnect events like:
logout - clients should stop trying to connect until a user logs in
server reboot - clients should reattempt connection until they get through
I need to be able to tell on the client side why a client was disconnected by the server, is there at least some way to make sure a message has sent before calling socket.disconnect()?
Edit: this appears specific to the node.js cluster code - when the application is run on a single thread it works as expected.
Solved this by setting up a Redis server and configuring socket.io to use it within node.js if anyone finds this looking for a solution to the issue.

Categories

Resources