I wanted to create a chat-like application so started using nodejs and socket.io. For simplicity (Firstly, I wanted to understand how it works), I made a button to emit message to the server which in turn should (in my novice understanding) change the content of the paragraph of all the web-pages currently pointing to that URL. My problem is, the content of webpage from which I emit the message gets changed but happens nothing to the same paragraph of other webpages pointing to same URL.
Here is my code:
// This is server.js
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs');
app.listen(8080);
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
socket.on('user_event', function (data) {
socket.emit("to_all_users","something has changed");
console.log(data);
});
});
The following is my HTML( client-side) file( ONLY THE RELEVANT SECTIONS):
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('to_all_users', function (data) {
var msgs=document.getElementById("my_messages");
msgs.innerHTML=data;
});
function send_to_server(){
socket.emit("user_event","Here is the new news");
}
</script>
</head>
<body>
<button onclick="send_to_server()">CHECKBUTTON</button>
<p id="my_messages">Here is the messages</p>
What I did: I opened two localhost:8080 on my google-chrome and clicked on the CHECKBUTTON of one of those.
What I expected: Paragraph with id=my_messages in both tab(localhost:8080) to change to the data- "Something has changed"
What actually happened: paragraph from where I clicked the button changed to desired string. It proved that the message went to the server and it was the server's emitted response that triggered the event in the page to change the paragraph. But nothing happened to the other (localhost:8080).
What am I missing? Am I fundamentally thinking in a wrong direction here?
change 1 line in server.js
// from
socket.emit("to_all_users","something has changed");
// to
io.sockets.emit("to_all_users", "something has changed");
Related
So I have a Raspberry Pi 4 and im trying to receive data from a JSON file and display it on a text element on my website. sorry if im totally wrong, it's my second day with a Raspberry Pi. I have done basic things like turn an LED on, thanks to w3schools. Im trying to make a bot hosting tool thing for myself, where it will display amount hosted on a TV
index.html:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="index.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>
</head>
<body>
<div class="container">
<h1>Bots Hosted:</h1>
<h2 id="bot-qty">0</h2>
</div>
</body>
<script>
var socket = io();
window.addEventListener("load", function() {
var bot_count = document.getElementById("bot-qty");
var times_ran = 0;
const interval = setInterval(function() {
socket.emit("request-count", times_ran);
times_ran++;
}, 20000);
})
socket.on('request-count', function(data) {
document.getElementById("bot-qty").innerText = data;
})
</script>
</html>
webserver.js:
var http = require('http').createServer(handler);
var fs = require('fs');
var io = require('socket.io')(http);
http.listen(1337);
function handler(req, res) {
fs.readFile(__dirname + '/public/index.html', function(err, data) {
if (err) {
res.writeHead(404, { 'Content-Type': 'text/html' });
return res.end("404 Not Found");
}
res.writeHead(200, { 'Content-Type': 'text/html' });
res.write(data);
return res.end();
});
}
io.sockets.on('connection', function(socket) {
socket.on('request-count', function(data) {
var bot_count = JSON.parse(fs.readFileSync("config.json", "utf8"));
console.log(bot_count);
socket.emit('request-count', bot_count);
});
});
In console, it says
GET <long_url_here> net::ERR_NAME_NOT_RESOLVER
In the index.html you initialize a new Socket instance by writing
var socket = io();
You don't provide any url, so the socket.io-client will use the default window.location as can be seen here. This might be a problem, so try to set a specific url, e. g.
var socket = io('http://localhost');
or (also specifying the port)
var socket = io('http://localhost:1337');
Also try to make sure that you run your webserver.js with node webserver.js prior to open the website.
Also see this discussion on GitHub.
My SocketIO server returns a count of 10 to 0 every second, but my web page only updates the number every 10-15 seconds. However, my NodeJS console well displays this count.
In addition, when I manually reload my web page, my browser shows me the correct figure, but suddenly I have to wait 10-15 seconds for it to display the next digit.
NodeJS part
var http = require('http');
var fs = require('fs');
require('events').EventEmitter.prototype._maxListeners = 100;
var server = http.createServer(function(req, res) {
fs.readFile('./serv.html', 'utf-8', function(error, content) {
res.writeHead(200, {"Content-Type": "text/html"});
res.end(content);
});
});
function envoi(p1){
var io = require('socket.io').listen(server);
io.sockets.on('connection', function (socket) {
socket.emit('message', p1);
});
}
main();
function main(){
var interval = setInterval(loop, 1000);
var a = 10;
function loop(){
if(a<1){
clearInterval(interval);
rolling();
}
else{
console.log(a);
a--;
envoi(a);
}
}
}
function rolling(){
console.log('ok');
main();
}
server.listen(8080);
HTML/JS part
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Socket.io</title>
</head>
<body>
<h1>Communication avec socket.io !</h1>
<div id='r'>Connection..</div>
<script src="jquery.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost:8080');
socket.on('message', function(message) {
document.getElementById('r').innerHTML = message;
})
</script>
</body>
</html>
Thank you :)
Nathan
There are a few problem with your server side socket.io code that could be causing issues.
Your envoi function is creating a new socket.io server in every loop execution. It is probably returning a cached version, but, you should only invoke listen once. Similar to how creating your http server operates. It should ideally follow your http server creation.
In the same vein, you should only register to the connection event once following your call to listen. You should then store the connected socket somewhere or use the io.socket property to retrieve connected sockets.
Your code that prints down the number should look something like this
let val = 10;
function pushNumber() {
io.sockets.emit('message', val); // Sends message to all sockets on default namespace
val--;
}
When I execute the following code, I get the error: Reference Error: Watershed is not defined. How can I define it? Do I need a module to be installed for it?
var restify=require('restify');
var ws= new Watershed();
var server=restify.createServer();
server.get('websocket/attach', function upgradeRoute(req, res, next){
if(!res.claimUpgrade){
next(new Error("Connection must be upgraded."));
return;
}
var upgrade=res.claimUpgrade();
var shed=ws.accept(req, upgrade.socket, upgrade.head);
shed.on('text', function (msg){
console.log("The message is: "+msg);
});
shed.send("hello there");
next(false);
});
server.listen(8081, function(){
console.log('%s listening at %s', server.name, server.url);
});
There is also a section of the restify doc that mentioned how to handle the ability to upgrade sockets. I just struggled with this for an emarrassingly long time and thought I'd share the simple solution. In addtion the #Dibu Raj reply, you also need to create your restify server with the handleUpgrades option set to true. Here is a complete example to make restify work with websocket upgrades and watershed:
'use strict';
var restify = require('restify');
var watershed = require('watershed');
var ws = new watershed.Watershed();
var server = restify.createServer({
handleUpgrades: true
});
server.get('/websocket/attach', function (req, res, next) {
if (!res.claimUpgrade) {
next(new Error('Connection Must Upgrade For WebSockets'));
return;
}
console.log("upgrade claimed");
var upgrade = res.claimUpgrade();
var shed = ws.accept(req, upgrade.socket, upgrade.head);
shed.on('text', function(msg) {
console.log('Received message from websocket client: ' + msg);
});
shed.send('hello there!');
next(false);
});
//For a complete sample, here is an ability to serve up a subfolder:
server.get(/\/test\/?.*/, restify.serveStatic({
directory: './static',
default: 'index.html'
}));
server.listen(8080, function() {
console.log('%s listening at %s', server.name, server.url);
});
For an html page to test your new nodejs websocket server: write this html below into a file at ./static/test/index.html - point your browser to http://localhost:8080/test/index.html - open your browser debug console to see the message exchange.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Web Socket test area</title>
<meta name="description" content="Web Socket tester">
<meta name="author" content="Tim">
</head>
<body>
Test Text.
<script>
(function() {
console.log("Opening connection");
var exampleSocket = new WebSocket("ws:/localhost:8080/websocket/attach");
exampleSocket.onopen = function (event) {
console.log("Opened socket!");
exampleSocket.send("Here's some text that the server is urgently awaiting!");
};
exampleSocket.onmessage = function (event) {
console.log("return:", event.data);
exampleSocket.close();
}
})();
</script>
</body>
</html>
Your browser log will look something like this:
07:05:05.357 index.html:18 Opening connection
07:05:05.480 index.html:22 Opened socket!
07:05:05.481 index.html:26 return: hello there!
And your node log will look like:
restify listening at http://[::]:8080
client connected!
Rest service called started
upgrade claimed
Received message from websocket client: Here's some text that the server is urgently awaiting!
Documentation for this found at:
http://restify.com/#upgrade-requests
You should include the watershed library
var Watershed = require('lib/watershed').Watershed;
I have multiple buttons with an attribute called groupName. They look like this:
SCENE I
SCENE II
SCENE III
I'm trying to figure out how to get socket.io to emit the link's groupName value when clicked. So when the first link is clicked, socket.io would emit "groupName - SCENE_I"
How could this be accomplished?
It seems you want something similar to a chat -- where a click on a link acts as a user sending a message to the server, and the server would emit that to a room (to other users, I suppose?)
If that's the case, you should take a look at this example: http://socket.io/get-started/chat/
You would do something like this on the client side:
<html>
<head>
</head>
<body>
SCENE I
SCENE II
SCENE III
<script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
<script>
$(document).ready(function(){
var socket = io();
// listen to server events related to messages coming from other users. Call this event "newClick"
socket.on('newClick', function(msg){
console.log("got new click: " + msg);
});
// when clicked, do some action
$('.fireGroup').on('click', function(){
var linkClicked = 'groupName - ' + $(this).attr('groupName');
console.log(linkClicked);
// emit from client to server
socket.emit('linkClicked', linkClicked);
return false;
});
});
</script>
</body>
</html>
On the server side, still taking the chat idea into consideration:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendfile('./index.html');
});
io.on('connection', function(socket){
// when linkClicked received from client...
socket.on('linkClicked', function(msg){
console.log("msg: " + msg);
// broadcast to all other users -- originating client does not receive this message.
// to see it, open another browser window
socket.broadcast.emit('newClick', 'Someone clicked ' + msg) // attention: this is a general broadcas -- check how to emit to a room
});
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
I have a node (0.6.11)/socket.io(0.9.0) application that runs well in FF but IE8 throws JS exceptions:
Access is denied
in socket.io.js (line 2561):
req.open(method || 'GET', this.prepareUrl() + query, true);
a few lines before that, req is defined as
req = io.util.request(this.socket.isXDomain())
This suggests it is a cross domain issue, but I'm doing it locally all the way. Plus FF has no issues.
What could be the cause?
.
Here's the source code:
SERVER:
var app = require('express').createServer()
, io = require('socket.io').listen(app);
app.listen(1337);
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
CLIENT:
<html>
<head>
</head>
<body>
<div id='contents'>
</div>
<script src="http://localhost:1337/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://127.0.0.1:1337');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
</script>
</body>
</html>
I read about setting the secure flag to true and that makes the exception go away but then it siliently fails and does nothing. In FF and IE.
sorry nobody bothers to answer you, but the issue is that you are doing CORS, (cross-origin-resource-sharing), meaning your socket.io server is running on a different port from your webserver (i assume port 80, but you don't explicitly say it)
the IE8 and IE9 have very limited CORS support. i don't know a solution for IE8 support, but that's your problem. more details can be found here: http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx