Error while getting messges from sockets in javascript - 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.

Related

Websocket: Is it necessary to send ping messages by hand? (e.g between fiber websocket server & js client in browser)

I've wrtten a websocket server in fiber's websocket, and the client is js websocket in browser.
Some questions regarding ping/pong:
Is there any default ping/pong msg between the websocket server & client?
If yes, then why I can't see it in chrome's devtools.
If there isn't any defult ping/pong msg, should I add ping/pong between server & client myself?
If it's a good practice to add ping/pong msg myself, then:
Is it better to send ping from client to server, or reverse?
Since conn.ReadJSON() will block, does that means I should use conn.SetPingHandler() to specify a handler, or just use the default handler?
In either case, the ping need to be sent from client to server I guess.
Sample ping from server (not sure is it proper)
I added a testing ping sent from fiber websocket server to js client, if needed:
// ping
// TODO: not sure is this needed ?
// TODO: use goroutine pool ?
if needPing {
go func() {
pingTicker := time.NewTicker(pingPeriod)
defer func() {
pingTicker.Stop()
}()
time.Sleep(pingPeriod) // wait a while before start ping,
for {
select {
case <-pingTicker.C:
conn.WriteControl(websocket.PingMessage, []byte("ping"), time.Now().Add(time.Second*5))
log.Debug("ping")
}
}
}()
}
I also don't see any ping msg on client in chrome's devtools.
It's better to use for{ select } to handle both ping & normal msg I guess, but conn.ReadJSON() would block the goroutine, might need to create a channel for it? Didn't try yet.
BTW, any suggestion to the ping impl?

Closing single node server connection closes them all

I barely ask any questions on Stack Overflow, but this one is beyond me. I guess I'm missing something basic as I'm pretty new to Node server.
Our application is pretty basic. The server is supposed to receive a handful of text lines (data), merge and parse them, and once the connection is closed (data sending is over) it sends the data to the api.
var net = require('net');
var fs = require('fs');
const axios = require('axios')
const server = new net.Server();
server.listen(PORT, IP);
server.on("connection", client => {
client.write("Hello\n");
console.log('connected');
let received = "";
client.on("data", data => {
received += data
console.log("Partial data is: " + data);
});
client.on("close", () => {
received = received.toString('utf8');
fs.appendFile('log.txt', received, function (err) {});
received = received.replace(/(?:\r\n|\r|\n)/g, "||");
axios.post(APIADDRESS, {data: received});
console.log('Full data is: '+ {data: received});
});
});
To send the data I'm simply running a netcat or nc using the netcat ipaddress port, that's not a problem. It's connecting fine, status message is received.
The thing is - once I open two or more connections from two DIFFERENT SSh servers something weird happens. I can send the line after line just fine. The server reports back "partial data" debug without problem, for both of them.
However, once I close one of the connections (ctrl+c) they BOTH close.
In the end, only the data from the manually closed connection is received. The other one, from a separate nc on a separate ssh server never reaches the client.on("close") part, it seems. It's just terminated for no reason.
Any ideas? I don't even know where to start.
//EDIT
Just tested it from my pc and some ssh mobile app using separated SSH servers. As soon as ctrl+c is sent at any device it closes the connection for all clients.
//Forgot to mention I'm running pm2 to keep the server up. Once I turned on the script by hand, ignoring pm2 - it works fine. Weird. It is happening because of PM2.
I would guess that you have Putty configured to ‘Share SSH connections if possible’. Per some doc, when doing so:
When this mode is in use, the first PuTTY that connected to a given server becomes the ‘upstream’, which means that it is the one managing the real SSH connection. All subsequent PuTTYs which reuse the connection are referred to as ‘downstreams’: they do not connect to the real server at all, but instead connect to the upstream PuTTY via local inter-process communication methods.
So, if you Ctrl+C the PuTTY session that is managing the actual shared connection, they both lose their connection.
You could presumably disable this shared connection feature at either the client or server end of things since both must be enabled for sharing to occur.
To anyone coming here in the future.
If you are using pm2 with --watch enabled and the text log file is in the same folder as your main server script... That's the reason why it drops the connection after a single client disconnects. It just detects that the log has changed.
I'm not facepalming, that's not even funny.

Web sockets, socket.io or other alternative

I'm kinda new on sockets related subject so I'm sorry for any dumb question.
I would like to do something like this… I have am hybrid app and a website, and I wanted that when I click in a button on the app, it shows me alert/notificaion on the website. I read about Socket io and it does the job on localhost, but I want na alternative that not uses a server behind, since I'm not being able to run it using CPANEL (What I have access to)
Is it possible to have like a "direct" connection from the app to the site when I click the button?
You can consider using firebase for this:
In your javascript:
// execute the following script on click
importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-messaging.js');
// Initialize the Firebase app in the service worker by passing in the
// messagingSenderId.
firebase.initializeApp({
'messagingSenderId': 'YOUR-SENDER-ID'
});
// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging();
messaging.send({data: "your data if you want to send"}).then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
// similarly, on your browser:
messaging.onMessage(function(payload) {
console.log('Message received. ', payload);
// ...
});
link: https://firebase.google.com/docs/
Hope it helps
Let's break the problem down into a few parts, starting with the transport to the browser, as that's what you're asking about.
Web Sockets are a way to establish a bi-directional connection between a server and a client. It's a standard implemented by most any modern browser. Socket.IO is a web-socket-like abstraction that can use Web Sockets or other transports under the hood. It was originally built as sort of a polyfill, allowing messages to be sent via Web Sockets, or even long-polling. Using Socket.IO doesn't give you any additional capability than you have with just the browser, but it does provide some nice abstractions for "rooms" and such.
If you're sending data only from the server to the client, Web Sockets aren't the ideal choice. For streaming of data in general, the Fetch API and ReadableStream are more appropriate. Then, you can just make a normal HTTP connection. However, what you're looking for is event-style data, and for that there are Server-Sent Events (SSE). https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events Basically, you instantiate an EventSource object on the client, pointed at a URL on the server. The client automatically maintains a connection, reconnecting if necessary. It's also capable of synchronizing to a point in the stream, providing the server with the last message received so that the client can be caught up to present time.
Now, how does your server endpoint know when to send this data, and what to send? Ideally, you'll use some sort of pub/sub system. These capabilities are built into Redis, which is commonly used for this. (There are others as well, if you don't like Redis for some reason.) Basically, when your server receives something from the app, the app is "publishing" a message to a particular channel where all "subscribers" will receive it. Your server will be that EventSource and can simply relay data (verifying it and authenticating of course, along the way).
You can write a PHP script that has a POST/GET endpoint. Your app will communicate to this endpoint. The endpoint needs to handle the message and write it to a database. Your website can then poll to see if there are any new entries, and show something if there are
Alright, let's do it in PHP. This is just the most basic example. Just put it somewhere and link to the script from your app.
<?php
function requestVars($type = 'REQUEST'){
if($type == 'REQUEST')
$r = $_REQUEST;
elseif($type == 'POST')
$r = $_POST;
elseif($type == 'GET')
$r = $_GET;
$ret = array();
foreach($r as $r1 => $r2)
$ret[$r1] = $r2;
return $ret;
}
$vars = requestVars(); //get variables from request
echo $vars['var1']; // var1 is what comes in from the client
?>
I haven't tested this, so if something is wrong let me know.

MQTT PUBACK web sockets

I'm working on HiveMQ Websocket Client and I'm facing some issues with the message delivery.
so, I've come across the word PUBACK
let me explain you about my understanding and then I will ask my question.
whenever we send a message with QOS1, the hivemq server will acknowledge the sender with a PUBACK callback.
Now, I'm planning to subscibe to onPubackReceived event in my websockets, but the event is not firing after sending the message.
My Code:
var clientId = ClientIdentifier;
mqtt = new Messaging.Client(
host,
port,
clientId);
var options = {
timeout: 3,
keepAliveInterval: 60,
useSSL: useTLS,
cleanSession: cleansession,
onSuccess: onConnect,
onFailure: function (message) {
connected = false;
setTimeout(MQTTconnect, reconnectTimeout);
}
};
mqtt.onConnectionLost = onConnectionLost;
mqtt.onMessageArrived = onMessageArrived;
mqtt.onPubackReceived = OnPubackReceived;
Both the onConnectionLost and onMessageArrived are firing properly when a connection lost and message arrived, but the onPubackReceived is not firing.
please let me know, if I have understood it correctly or if I'm doing some mistake?
This not a HiveMQ issue.
My assumption is, that you used the HiveMQ Websocket Client as a starting point for your implementation.
In any case a Paho MQTT Client does not have a onPubackReceived field.
If you provide more details about your use case or what's your issue with message delivery, I might be able to point you into the right direction.
EDIT:
What you are describing is called Quality of Service 1 in MQTT. It is a guarantee, that a message is received at least once.
It is the client implementation's job to keep this guarantees and therefor resend a message, should a PUBACK not be received. Manually interfering with this behaviour in your application would result in inconsistency regarding the client's persistence.
For clarification:
Simply setting duplicate=truewill not result in a message being recognised as a duplicate. It will also have to have the the same messageID as the original.
I was not able to actually find any documentation about paho.jskeeping the Quality of Service = 1.
However, MQTT.js does.
QoS 1 : received at least once : The packet is sent and stored as long as the client has not received a confirmation from the server. MQTT ensures that it will be received, but there can be duplicates.
To sum things up:
Resending of messages, no PUBACK was received on, is the client Object's job. This is part of the MQTT specification.
Using the MQTT.js works over Websockets and ensures to keep QoS levels
Hope this helps.

Correct way to handle Websocket

I've a client to server Websocket connection which should be there for 40 seconds or so. Ideally it should be forever open.
The client continually sends data to server and vice-versa.
Right now I'm using this sequence:
var socket;
function senddata(data)
{
if (!socket)
{
socket = new WebSocket(url);
socket.onopen = function (evt) {
socket.send(data);
socket.onmessage = function (evt) {
var obj = JSON.parse(evt.data);
port.postMessage(obj);
}
socket.oneerror = function (evt) {
socket.close();
socket = null;
}
socket.onclose = function(evt){
socket = null;
}
}
}
else
{
socket.send(data);
}
}
Clearly as per current logic, in case of error, the current request data may not be sent at all.
To be frank it sometimes gives error that websocket is still in connecting state. This connection breaks often due to networking issues. In short it does not work perfectly well.
I've read a better design : How to wait for a WebSocket's readyState to change but does not cover all cases I need to handle.
Also I've Googled about this but could not get the correct procedure for this.
So what is the right way to send regular data through Websockets which handles well these issues like connection break etc?
An event you don't seem to cover is onclose. Which should work really well, since it's called whenever the connection terminates. This is more reliable than onerror, because not all connection disruptions result in an error.
I personally use Socket.IO, it enables real-time bidirectional event-based communication between client and server.
It is event driven. Events such as
on connection :: socket.on('conection',callback);
and
on disconnect :: socket.on('disconnect',callback);
are built in with socket.io so it can help you with your connection concerns. Pretty much very easy to use, check out their site if you are interested.
I use two-layer scheme on client: abstract-wrapper + websocket-client:
The responsibilities of the websocket-client are interacting with a server, recovering the connection and providing interfaces (event-emitter and some methods) to abstract-wrapper.
The abstract-wrapper is a high-level layer, which interacts with websocket-client, subscribes to its events and aggregating data, when the connection is temporary failed. The abstract-wrapper can provide to application layer any interface such as Promise, EventEmitter and so on.
On application layer, I just work with abstract-wrapper and don't worry about connection or data losing. Undoubtedly, it's a good idea to have here information about the status of connection and data sending confirmation, because it's useful.
If it is necessary, I can provide some code for example
This apparently is a server issue not a problem in the client.
I don't know how the server looks like here. But this was a huge problem for me in the past when I was working on a websocket based project. The connection would continuously break.
So I created a websocket server in java, and that resolved my problem.
websockets depend on lots of settings, like if you're using servlets then servlet container's settings matter, if you're using some php etc, apache and php settings matter, for example if you create a websocket server in php and php has default time-out of 30 seconds, it will break after 30 seconds. If keep-alive is not set, the connection wont stay alive etc.
What you can do as quick solution is
keep sending pings to a server after a certain amount of time (like 2 or 3 seconds, so that if a websocket is disconnected it is known to the client so it could invoke onclose or ondisconnect, I hope you know that there is no way to find if a connection is broken other than failing to send something.
check server's keep-alive header
If you have access to server, then it's timeouts etc.
I think that would help

Categories

Resources