How can a Node script send a notification via XMPP to a Jabber user (e.g. via Google Hangouts)? I've looked at libraries like xmpp/client but they seem overkill. Is there a simpler solution?
Simplest way to send a message via XMPP in Node
There is probably no other simpler XMPP client library for Node than node-simple-xmpp.
In this case the minimal Node.js script to send a message to another Jabber user is:
var xmpp = require('simple-xmpp');
var jid = 'testjs#xmpp.jp';
var pwd = 'xyz';
var server = 'xmpp.jp';
var port = 5222;
xmpp.on('online', function(data) {
console.log('Connected with JID: ' + data.jid.user);
xmpp.send('testjs#007jabber.com', 'hello! time is '+new Date(), false);
});
xmpp.on('error', function(err) {
console.error("error:", JSON.stringify(err));
});
xmpp.connect({
jid: jid,
password: pwd,
host: server,
port: port
});
If the two account have never spoken together, a preliminary 'subscribe' is also required:
xmpp.subscribe('testjs#007jabber.com');
As you can see in package.json node-simple-xmpp lib has a dependency on [node-xmpp-client] (https://github.com/xmppjs/xmpp.js/tree/node-xmpp/packages/node-xmpp-client).
Usage with Google Talk/Hangouts
The script above is working (tested) also with Google Talk/Hangouts, you just have to replace xmpp.jpserver with talk.google.com and use a Google account. Turn on https://myaccount.google.com/lesssecureapps to enable Node.js script to sign in with Google account.
Other XMPP libraries
As of https://npms.io/search?q=node-xmpp there are a few other XMPP Client libraries for Node, however almost all of them are dependent on node-xmpp-client or limited to BOSH connection (polling over HTTP).
One interesting lib for those used to Strophe.js on client side seems node-strophe. It is based on Strophe.js release 1.0.2 which is a library for applications that run in any browser. Unfortunately that version didn't support other than BOSH (see Strophe.js changelog), websocket is available only since release 1.1.0.
Exploring alternatives without specific XMPP libraries
An alternative solution without specific XMPP libraries could be using Net module, but in this case you need to manage all XMPP interactions to establish the connection to the server, see https://wiki.xmpp.org/web/Programming_XMPP_Clients .
Below is a very raw example of script trying to initiate the connection with a Jabber server using Net module:
var net = require('net');
var jid = 'testjs#xmpp.jp';
var pwd = 'xyz';
var server = 'xmpp.jp';
var port = 5222;
var msg = '<stream:stream xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0" to="'+server+'">';
var client = new net.Socket();
client.connect(port, server, function() {
console.log('Connected');
client.write(msg);
});
client.on('data', function(data) {
console.log('Received: ' + data);
});
You can see in the console log the correct answer of Jabber server, however from then on it's a mess: you should begin exchanging TLS messages (see https://xmpp.org/rfcs/rfc3920.html#tls)
Conclusions
I think the only feasible alternative is the first one using node-simple-xmpp library.
Related
I am making a control panel for my Minecraft mining turtle and I need to communicate between the two using websockets. I have troubleshooted the Lua side of things and that works as intended when I connected it to a echo server.
Code here:
local ws,err = http.websocket("wss://localhost:5757")
if ws then
ws.send("Hello")
print(ws.receive())
ws.close()
end
However, I can not get the NodeJS side to work. I have tried different ports, I've tried opening ports.
Code here:
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 5757 });
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) {
console.log('received: %s', message);
});
ws.send('testing 123');
});
I can't figure out where I have gone wrong. All help is appreciated.
EDIT: Thought I'd add that it's not giving errors either, that I am using the ws npm package and running the latest LTS node version.
EDIT 2: I tried this code example here
const WebSocket = require('ws');
const ws = new WebSocket('wss://echo.websocket.org/');
ws.on('open', function open() {
ws.send('testing 123');
});
ws.on('message', function incoming(data) {
console.log(data);
});
And it worked and replied with 'testing 123' so it seems that the web socket doesn't want to run on local host.
I have a node server (Meteor.js) that should communicate with another server using websockets.
As the communication is between servers that don't involve direct users, I've chosen to use a self signed certificate.
Where to add the certificate parameters from the node server (which is a client to the other server)
var soc = new WebSocket("wss://localhost:9000")
I've tested connecting in insecure mode with certification and it works fine.
var soc = new WebSocket("ws://localhost:9000")
Connecting from android application in secure mode after adding the certificates to the application works fine too.
I've found this solution, the part that allows the client to connect to a secure socket with a self-signed certificate is:
"rejectUnauthorized: false"
It accepts all certificates but it still keeps the connection encrypted.
'use strict';
var WebSocket = require('ws');
var soc = new WebSocket("wss://localhost:9000", {
protocolVersion: 8,
origin: 'https://localhost:9000',
rejectUnauthorized: false
});
console.log("launched");
soc.onopen = function (event) {
console.log("Sending message");
soc.send('{}');
};
soc.onmessage = function (event) {
console.log(event.data);
}
soc.on('error', function(event) {
console.log(event);
});
So I am trying to make some sort of connection between my Java app and my Web app, I looked up websockets and they look really simple and easy to use :). And I created myself a Java Server, which uses the ServerSocket class.
Now the problem is I am able to connect to the server from the web, with the websocket, but I am unable to send data to the server... but when I tried to send data from a Java Client it worked fine... what might be the problem?
My Java/Scala (I followed this tutorial: https://www.tutorialspoint.com/java/java_networking.htm) server:
class Server(val port: Int) extends Thread {
private val serverSocket = new ServerSocket(port)
override def run(): Unit = {
try {
while(true) {
println("Waiting for client on port: " + serverSocket.getLocalPort)
val server = serverSocket.accept()
println(server.getRemoteSocketAddress)
val in = new DataInputStream(server.getInputStream())
println(in.readUTF())
val out = new DataOutputStream(server.getOutputStream())
out.writeUTF("Hello world!")
server.close()
}
} catch {
case s: SocketTimeoutException => println("Connection timed out!");
case e: Exception => e.printStackTrace()
}
}
}
My web js (I followed https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications ):
/**
* Created by samuelkodytek on 20/12/2016.
*/
var conn = new WebSocket('ws://127.0.0.1:8080');
conn.onopen = function(e) {
console.log("Connection established!");
conn.send("Hello!");
};
conn.onmessage = function(e) {
console.log(e.data);
};
A web socket server is not the same thing as a simple socket server. A server that offers web sockets must first offer HTTP or HTTPS services because the web socket is established when a web client sends an HTTP request with an Upgrade option and special fields for establishing the web socket. Even after the web socket is established, the connection still does not behave exactly like a regular socket. The Web Socket protocol uses frames to send or receive data. This is all considerably different from what you seem to expect.
One other thing that you should be aware of is that the browser will enforce the rule that the web socket must come from the same host as the page that is attempting to establish the web socket (the same protocol, address, and TCP port).
In the following snippet, a tutorial author shows how to alter the original tutorial to include an http server. Here's the snippet.
var http = require(‘http’),
fs = require(‘fs’),
io = require(‘socket.io’),
index;
fs.readFile(‘./chat.html’, function (err, data) {
if (err) {
throw err;
}
index = data;
});
var server = http.createServer(function(request, response) {
response.writeHeader(200, {“Content-Type”: “text/html”});
response.write(index);
response.end();
}).listen(1223);
//and replace var socket = io.listen(1223, "1.2.3.4"); with:
var socket = io.listen(server);
The code in the original tutorial didn't include the http server, and socket was defined as simply:
var socket = io.listen(1223, "1.2.3.4");
I noticed that he replaces the variable's content io.listen(1223, "1.2.3.4"); with server which doesn't include the ip (1.2.3.4) anywhere.
My Question:
What is the purpose/effect of the referenced IP address?
Why is it excluded when passing an http server to create the socket?
When you are listening on a port, you can optionally include the IP address of a specific interface to listen on. For example, you might have several network interfaces with several IP addresses, and only want your service running on one of them. A more common use case is that you only want your server accessible on localhost, so you might have it listen only on 127.0.0.1.
Now, when you call io.listen(server) where server is an existing Node.js HTTP server, Socket.IO isn't actually opening a new listening connection at all. This is a shortcut for Socket.IO to wrap its methods on the existing HTTP server. If you wanted to specify a specific interface address to listen on, you would need to do it where .listen() is called on the HTTP server, above where you call io.listen(server).
More info in the documentation for raw network sockets in Node.js: http://nodejs.org/api/net.html#net_server_listen_port_host_backlog_callback
I just started up learning how to make web applications. I am making a webserver in nodejs (a to-do list app). I am using the express framework, and mongodb as database. For communication between the client and the server i am using socket.io.
I can't find a way to make it so that when the server emits and event the client will update the info on all of his open windows of the page. Right now the info updates only on the window that triggered the event on ther server. This is the server code:
Server code:
var io = require('socket.io').listen(server);
io.of('/home').on('connection', function (socket) {
socket.on('newListGroup', function (data) {
...
socket.emit('groupNo', obj);
});
}); `
Client javascript:
var socket = io.connect('http://localhost/login');
socke.on('groupNo', function(data){ ... });
$('#newListGroup').blur(function() {
socketLogin.emit('newListGroup', {newGroup:newGroup});
});
Can this work or should I take another approach?
You can broadcast a message to all sockets like this:
var io = require('socket.io').listen(server);
io.of('/home').on('connection', function (socket) {
socket.on('newListGroup', function (data) {
socket.broadcast.emit('groupNo', obj); });
});
It should be limited to the namespace but you will probably have to implement your own logic for broadcasting only to windows on the same client (probably using authentication) if that is what you want to do.