Redis pub/sub for chat server in node.js - node.js

I'm trying to work the Redis Cookbook example:
var http = require('http'),
io = require('socket.io')
fs = require('fs'),
redis = require('redis'),
rc = redis.createClient(9189, "pike.redistogo.com");
rc.auth("passwd", function() {
console.log("Connected! to redistogo!");});
rc.on("connect", function() {
rc.subscribe("chat");
console.log("rc connect event");
});
I am successful through here but never get "message."
rc.on("message", function (channel, message) {
console.log("Sending: " + message);
socketio.sockets.emit('message', message);
});
webpage = http.createServer(function(req, res){
console.log('webpage request starting...');
fs.readFile('./index.htm', function(error, content) {
if (error) {
res.writeHead(500);
res.end();
}
else {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(content, 'utf-8');
}
});
});
webpage.listen(7777);
my client side index.htm is this
<!docttype html>
<html lang="en">
<head>
<script src ="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"> </script>
<script src="http://www.heaphash.com:7777/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('www.heaphash.com', { port: 7777});
socket.on('message', function(data){
var li = new Element('li').insert(data);
$('messages').insert({top: li});
}
</script>
<meta charset="utf-8">
<title>Chat with Redis</title>
</head>
<body>
<ul id="messages">
<!-- chat messages go here -->
</ul>
<form id="chatform" action="">
<input id="chattext" type="text" value="" />
<input type="submit" value="Send" />
</form>
<script>
$('#chatform').submit(function(){
socket.emit('message', $('chattext').val());
$('chattext').val(""); //cleanup the field
return false;
});
</script>
</body>
</html>
how does a client publish to a specific Redis "chat" channel.

If you are using redis pub/sub functionality within your node.js program you should dedicate one redis client connection for listening on some channel and second redis client connection for sending normal commands and/or publishing messages to your channel(s). From node_redis docs:
When a client issues a SUBSCRIBE or PSUBSCRIBE, that connection is put
into "pub/sub" mode. At that point, only commands that modify the
subscription set are valid. When the subscription set is empty, the
connection is put back into regular mode.
If you need to send regular commands to Redis while in pub/sub mode,
just open another connection.
Your problem is also related to these questions:
Redis / Node.js - 2 clients (1 pub/sub) causing issues with writes
Why can't I have a single Redis client acting as PUB and Sub in the same connection?

I believe that the example from that book is missing something, I also read that book and wondered. You are subscribed to the Redis channel and are waiting for messages on the server side, but you never publish to that channel. What is missing is an event listener so when there is a websocket message, you publish that message to the redis channel.

Related

I cannot connect to a sites socket

I've been trying to do this but can you connect to another websites their socket.io server? I've been trying to scrape data from a website that uses socket.io for live updates. It would be very handy if this were to be possible.
I'm trying to get live updates from the website https://www.ethercrash.io/ - However I tried the following code and wouldn't get any updates other than a connection;
var io = require('socket.io-client');
var socket = io('https://www.ethercrash.io')
socket.on('connect', function(){
console.log(true);
});
socket.on('msg', function(data) {
console.log('chat message');
});
socket.on('disconnect', function(){
console.log(false);
});
Am I doing something wrong or is this just not possible?
I use the following in all my node.js / express / socket.io projects. Hopefully it helps you out.
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script>
<script>
$(document).ready(function() {
// NOTE, I AM FORCING WEBSOCKET TRANSPORT HERE. AND AM NOT ALLOWING
// SOCKET.IO TO FALL BACK TO LONG POLLING FALLBACK,
// SO YOU CAN REMOVE THE TRANSPORTS AND GO WITH SOCKET.IO DEFAULTS
// PORT I'M USING IS 3000 -- SO THE PORT CAN BE IMPORTANT, DEPENDING ON YOUR USASGE
var socket = io.connect("https://MY-SERVER-NAME-HERE.eastus.cloudapp.azure.com:3000", {
secure: true,
transports: ["websocket"],
path: "/socket/socket.io"
});
// EVERY TIME THE NODE.JS SERVER SENDS US 'MESSAGE' WE'LL DISPLAY THAT UPDATED NUMBER IN A DIV
socket.on("message", function(msg) {
document.getElementById("message").innerHTML = msg;
});
});
</script>
</head>
<body style="width: 100%;">
<div id="message" style="text-align: center; width: 100%; font-size: 2em;"></div>
</body>
</html>
You also are depending on that 'other site' (running the socket server) emitting out to either ALL connected clients or to your connection specifically. Unless either of those happen, you will only have a connection with no messages being emitted out (to be read / parsed).
Sockets are really fun to work with and full of potential once you get the hang of it!

socket.io node.js server "debug: destroying non-socket.io upgrade" message

I have a node.js socket server using socket.io.
I'm building a firefox addon, where I load a pageworker. The html in the following page is as follows:
<html>
<head>
<script type="text/javascript">
//THIS DOESN'T WORK
var exampleSocket = new WebSocket("ws://someip:port");
exampleSocket.onopen = function (event) {
console.log("socket opened!");
};
//THIS WORKS
var exampleSocketa = new WebSocket("ws://echo.websocket.org");
exampleSocketa.onopen = function (event) {
console.log("socket to echo opened!");
};
</script>
</head>
<body>
</body>
</html>
I can open a websocket to echo.websocket.org, but not my own server. I get a "debug: destroying non-socket.io upgrade" message. I can switch it off with the option: { 'destroy upgrade': false }, but then I see no debug output from server, and no connection is made.
What am I doing wrong? How can I get a socket open to my socket.io server?
So after some more googling, it turns out that I need to require socket.io on the client side. Even though socket.io uses websockets, it prefers talking to itself.

Client disconnects immediately after connection to Node js TCP server

This is my first time with node js. I am trying to get the client to connect to the server and maintain the connection without closure.
This is all hosted in an ubuntu server edition hosted in a virtualbox.
I had checked that the server is actually listening to the port 5000 using
netstat -ant
Websockets is also available on my browser.
I get the following output with error
Echo server dot come
192.168.1.107
node.js:134
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: EPIPE, Broken pipe
at Socket._writeImpl (net.js:159:14)
at Socket._writeOut (net.js:450:25)
at Socket.write (net.js:377:17)
at Socket.ondata (stream.js:36:26)
at Socket.emit (events.js:81:20)
at Socket._onReadable (net.js:678:14)
at IOWatcher.onReadable [as callback] (net.js:177:10)
and if i call socket.end() on the server on connection event handler i get a disconnecting client. My question is how to establish a stable connection using this code, what do i have to change or i am doing wrong here? pulling my hair out - thanks in advance!
HTML CODE
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Test RS Server (built over nodejs)</title>
<link rel="stylesheet" href="style.css"></link>
<script src="jquery.min.js" ></script>
<script src="client.js" ></script>
</head>
<body>
<label>Message</label>
<input type="text" id="message_box"></input>
<input type="button" id="submit_btn" value="Send"></input>
<div style="clear:both;"/>
<label>Output</label>
<textarea rows="10" cols="100" id="output_box"></textarea>
</body>
</html>
CLIENT JS
var message_box;
var output_box;
var submit_btn;
var url = "wss://192.168.1.107:5000";
var socket;
function createListeners() {
if ("WebSocket" in window) {
output_box.html("Supports sockets.");
socket= new WebSocket(url);
socket.onopen= function() {
socket.send("con opened");
output_box.html("Connection opened.");
};
socket.onmessage= function(response) {
// alert('got reply '+s);
console.log(response);
output_box.html(response);
};
socket.onclose = function() {
// websocket is closed.
output_box.html("Connection is closed...");
};
submit_btn.click(function(e) {
socket.send(message_box.val());
});
} else {
output_box.html("doesnt support sockets");
};
};
$(document).ready(function() {
message_box = $("#message_box");
output_box = $("#output_box");
submit_btn = $("#submit_btn");
createListeners();
});
SERVER JS CODE
var net = require('net');
var server = net.createServer(function (socket) {
socket.write('server says this\r\n');
socket.pipe(socket);
});
server.on('connection', function(socket) {
socket.write("Echo server dot come\r\n"+socket.address().address);
console.log("Echo server dot come\r\n"+socket.address().address);
// socket.end();
socket.pipe(socket);
});
server.listen(5000);
You are trying to use WebScoket client with simple TCP server. This is a different protocols. You need to setup WebSocket server to make it work. You can use websocket module to do that. Look at the server example code here.

socket.io get data from onclick action then pass the data to other pages to execute the data

I want to create a page using node.js and socket.io.
There are two buttons inside the page, when I click one of them, it will change a variable which defines the animation-duration(I omit the CSS animation codes here).
When I open the same page on another web-browser and click one of the buttons, I hope to see the change in both of the webpages. I don't know how to write the code inside the socket.on('chat', function(data){???}); to make two pages communicate with each other.
Client side:
//socket.io codes--
<script type="text/javascript" charset="utf-8">
var socket = io.connect('http://localhost:3000');
socket.on('chat', function (data)
{
function change_position(data)
{
document.getElementById("animation1").style.WebkitAnimationDuration=data;
}
});
</script>
.....
//action--
<body>
<button id="1b" type="button" style="position:absolute; left:377px; top:220px;" value="2s"; onclick="change_position(value)"> - 1 - </button>
<button id="2b" type="button" style="position:absolute; left:477px; top:220px;" value="15s"; onclick="change_position(value)"> - 2 - </button>
</body>
server side:
var io = require('socket.io'),
connect = require('connect');
var app = connect().use(connect.static('public')).listen(3000);
var chat_room = io.listen(app);
chat_room.sockets.on('connection', function (socket) {
socket.on('chat', function (data) {
chat_room.sockets.emit('chat', data);
});
});
If your want a message to propagate to all clients/sockets, in your server you should have something like:
chat_room.sockets.on('connection', function (socket) {
socket.on('chat', function (data) {
socket.broadcast.emit('chat', data);
socket.emit('chat',data);
});
});
The line socket.emit('chat',data); allows you to send the message back also to the sender of it, because broadcast will send it all other sockets.
Of course, you could ommit that line and handle the message sending logic in the client; i.e. adding some JavaScript code that makes the changes you want just after sending the message to the server.
You can emit on your client using socket.emit('message', data). Then on the server get it with chat_room.socket.on('message', data). Emit it to the clients using chat_room.sockets.emit('message', data).

Can't find path for socket.io.js

I have my node.js and socket.io setup and running perfectly on my local machine, but now I am trying to transfer it to my live server.
I have installed node.js and socket.io and they're working, but I can't seem to link to the socket.io/socket.io.js file through my client. It keeps coming back with "500 Internal Server Error"
I have tried using both these paths:
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
and
<script type="text/javascript" src="https://localhost:8080/socket.io/socket.io.js"></script>
Why isn't it being found?
"500 Internal Server Error" usually means "server crash" or at least "server encountered an exception". So the problem might not a missing socket.io.js.
Regardless, when I have a discrepancy between local working and remote not working, it's sometimes due to a difference in the environment variables. Where are you deploying your node.js? Heroku, EC2, Joyent?
Have you changed the connection-string? Have you checked with the browser inspector, if the javascript-file is loaded?
var sio = io.connect('http://yourdomain.com:80');
sio.socket.on('error', function (reason){
console.error('Unable to connect Socket.IO', reason);
});
Here i post two files one is chat.js and other is chat.html . This has the path for socket.io.js in html.this works.
1) chat.js :
var io = require("socket.io");
var socket = io.listen(1223);
socket.set("log level", 1);
var people = {};
socket.on("connection", function (client) {
client.on("join", function(name){
people[client.id] = name;
client.emit("update", "You have connected to the server.");
socket.sockets.emit("update", name + " has joined the server.")
socket.sockets.emit("update-people", people);
});
client.on("send", function(msg){
socket.sockets.emit("chat", people[client.id], msg);
});
client.on("disconnect", function(){
socket.sockets.emit("update", people[client.id] + " has left the server.");
delete people[client.id];
socket.sockets.emit("update-people", people);
});
});
2) chat.html :
<!DOCTYPE html>
<html lang="en">
<head>
<script src="http://localhost:1223/socket.io/socket.io.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"> </script>
<script>
$(document).ready(function(){
var socket = io.connect("127.0.0.1:1223");
$("#chat").hide();
$("#name").focus();
$("form").submit(function(event){
event.preventDefault();
});
$("#join").click(function(){
var name = $("#name").val();
if (name != "") {
socket.emit("join", name);
$("#login").detach();
$("#chat").show();
$("#msg").focus();
ready = true;
}
});
$("#name").keypress(function(e){
if(e.which == 13) {
var name = $("#name").val();
if (name != "") {
socket.emit("join", name);
ready = true;
$("#login").detach();
$("#chat").show();
$("#msg").focus();
}
}
});
socket.on("update", function(msg) {
if(ready)
$("#msgs").append("<li>" + msg + "</li>");
})
socket.on("update-people", function(people){
if(ready) {
$("#people").empty();
$.each(people, function(clientid, name) {
$('#people').append("<li>" + name + "</li>");
});
}
});
socket.on("chat", function(who, msg){
if(ready) {
$("#msgs").append("<li><strong><span class='text-success'>" + who + "</span></strong> says: " + msg + "</li>");
}
});
socket.on("disconnect", function(){
$("#msgs").append("<li><strong><span class='text-warning'>The server is not available</span></strong></li>");
$("#msg").attr("disabled", "disabled");
$("#send").attr("disabled", "disabled");
});
$("#send").click(function(){
var msg = $("#msg").val();
socket.emit("send", msg);
$("#msg").val("");
});
$("#msg").keypress(function(e){
if(e.which == 13) {
var msg = $("#msg").val();
socket.emit("send", msg);
$("#msg").val("");
}
});
});
</script>
</head>
<body>
<div class="row">
<div class="span2">
<ul id="people" class="unstyled"></ul>
</div>
<div class="span4">
<ul id="msgs" class="unstyled"></ul>
</div>
</div>
<div class="row">
<div class="span5 offset2" id="login">
<form class="form-inline">
<input type="text" class="input-small" placeholder="Your name" id="name">
<input type="button" name="join" id="join" value="Join" class="btn btn-primary">
</form>
</div>
<div class="span5 offset2" id="chat">
<form id="2" class="form-inline">
<input type="text" class="input" placeholder="Your message" id="msg">
<input type="button" name="send" id="send" value="Send" class="btn btn-success">
</form>
</div>
</div>
</body>
</html>
Run chat.js using command - node chat.js
and run chat.html in browser.
I know it's been 8 years old but I faced the same error, maybe my explanation could help someone.
By "trying to transfer to my live server" I did deploying it to virtual shared hosting that is running Node through Passenger module of Apache. Then I contacted the tech support and they said the script is starting to listen some ports and crashes and it is simply not possible on this type of hosting plan, I should apply for VPS/VDS instead.
It sounds strange because the app did not even start to listen, it's just about accessing static files. But probably the way Express is delivering static files is not working. Logs say:
[pid 66771] 19:33:18 listen(12, 511) = -1 EPERM (Operation not permitted)
events.js:183
throw er; // Unhandled 'error' event
^
I was able to read Express is using "stream" (nodejs.org/api/stream.html) to deliver static files and I have a suggestion it is simply not working on that type of hosting. The other static files are existing physically so they are delivered with Nginx and they do not fail. This makes some surprise as some files are loaded and some give error 500, not even 4xx when the resource can't be located.
Basically response 500 tells us the output unexpectedly ended. The logs say "end of script before headers". It is unpleasant when you can't access any log messages and just receive response 500 and have to contact support to see the logs.

Resources