I've found this script for reading a file an "broadcast" its content to every connection.
var serverServiceConfig={port: 8081};
var express = require("express");
var app = express();
var fs = require('fs');
var socket = require('socket.io');
function readTick(ws){
fs.readFile('tick.json', 'utf8', function (err,data) {
if (!err) {
try {
ws.emit('ticks', data);
} catch (e) {
// handle error
console.log('can not read file');
}
}
});
setTimeout(function () {
readTick(ws);
}, 200);
}
console.log('server is running ...');
app.configure(function(){
app.use(express.static(__dirname + '/'));
});
var server = app.listen(serverServiceConfig.port);
var io = socket.listen(server);
io.sockets.on('connection', function (socket) {
readTick(socket);
socket.on('disconnect', function (socket) {
});
});
The server starts without an error, so far so good. But if i try to connect to the server via ip:port i get the following message:
Cannot GET /
I tested this script on my local machine and it worked (a couple of weeks ago)
From what i "know" or i think is that a route is missing, or?
Any help is more than welcome.
Thank you in advance
Instead of using that function, you should put it in app.get('/', function(){//whatever you want to do//})
Related
I am using Adonis 4.1.0 and Adonis-websocket is only been available for v3. Can anyone tell me workaround for using socket.io with Adonis 4.1.0?
apparently they have been working on this not long ago, it was based on socket.io but because of some issues like memory leaks and others, they decided to use websockets directly instead, check these discussions :
https://github.com/adonisjs/discussion/issues/51
https://forum.adonisjs.com/t/integrating-socket-io-with-adonis-4/519
have you tried using socket.io without relying on Adonis ? ,
something like :
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket){
console.log('a user connected');
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
But you should be able to do this with Adonis by now according to : https://github.com/adonisjs/adonis-websocket-protocol
Example :
const filereader = require('simple-filereader')
const msgpack = require('msgpack-lite')
const packets = require('#adonisjs/websocket-packets')
const client = new WebSocket('ws://localhost:3000/adonis-ws')
client.onopen = function () {
// TCP connection created
}
client.onerror = function () {
// TCP connection error
}
client.onmessage = function (message) {
filereader(message, function (error, payload) {
const packet = msgpack.decode(payload)
handlePacket(packet)
})
}
function handlePacket (packet) {
if (packets.isOpenPacket(packet)) {
console.log('Server ack connection. Make channel subscriptions now')
}
if (packets.isJoinAck(packet)) {
console.log('subscription created for %s', packet.d.topic)
}
}
check this for broadcast examples using WS : https://github.com/websockets/ws#broadcast-example
Create start/socket.js file and paste following code inside it.
const Server = use('Server')
const io = use('socket.io')(Server.getInstance())
io.on('connection', function (socket) {
console.log(socket.id)
})
From Virk Himself in this forum:https://forum.adonisjs.com/t/integrating-socket-io-with-adonis-4/519
create a standalone socket io configuration file in start/socket.js
const io = require('socket.io')();
io.listen(3000);
io.on('connection', function (socket) {
console.log(socket.id)
})
to start your socket io server you can configure your server.js as below
new Ignitor(require('#adonisjs/fold'))
.appRoot(__dirname)
.preLoad('start/socket') //path of socket.js
.fireHttpServer()
.catch(console.error)
now when you start your server then it will start along with socket io
I have a REST api hosted on Amazon EC2, which is written with Nodejs (Express).
In a particular REST call, a reply of about 5MB is sent to the client. Before the client completely receives the reply, client prints following error message.
Premature end of Content-Length delimited message body
I added a connection listener in nodejs server like below to check what is going on the server.
var app = express();
var server = http.createServer(app);
var port = app.get('port');
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
server.on('connection', function (socket) {
log.debug('SOCKET OPENED' + JSON.stringify(socket.address()));
socket.setTimeout(300000); //5 minute timeout
socket.on('end', function () {
log.debug('SOCKET END: other end of the socket sends a FIN packet');
});
socket.on('timeout', function () {
log.warn('SOCKET TIMEOUT');
});
socket.on('error', function (error) {
log.warn('SOCKET ERROR: ' + JSON.stringify(error));
});
socket.on('close', function (had_error) {
log.debug('SOCKET CLOSED. IT WAS ERROR: ' + had_error);
});
});
I observed that SOCKET TIMEOUT gets logged in backend. In above code, I have increased the socket timeout to 5 minutes, but it doesn't seem to have any effect.
Earlier I had the REST API hosted in Google compute engine, and I didn't have this problem back then.
What could be the problem here?
Edit: Here is the code of REST API call.
I have following code in my app.js
require('./routes/index')(app);
Following is the index.js of routes directory.
var changeCase = require('change-case');
var express = require('express');
var routes = require('require-dir')();
module.exports = function (app) {
Object.keys(routes).forEach(function (routeName) {
var router = express.Router();
require('./' + routeName)(router);
app.use('/api/' + changeCase.paramCase(routeName), router);
});
};
As it can be seen, it loops through all the js files in the routes directory and registers the file name as the URL path in app.
Here is the code of this particular route for which I face this problem.
module.exports = function (router) {
router.get("/fetch", function (req, res, next) {
itemModel.fetch(req.user.clientId, function (error, items) {
if (error) {
res.status(500).json({error: error});
} else {
res.json(items); //items is a JSON array
}
});
});
}
Setting timeout for the HTTP server resolved the issue.
var server = http.createServer(app);
var port = app.get('port');
server.listen(port);
server.setTimeout(300000, function (socket) {
});
Tried different methods, but the data is sent to a maximum of one or two clients. How to send data to all the clients connected to the server ? What am I doing wrong?
Server.js:
var PORT = 3000;
var options = {
// 'log level': 0
};
var express = require('express');
var app = express();
var http = require('http');
var server = http.createServer(app);
var io = require('socket.io').listen(server, options);
server.listen(PORT);
app.get('/', function (req, res) {
res.sendfile(__dirname + '/attantions/templates/.default/template.php');
});
io.sockets.on('connection', function (client) {
client.on('attantion', function (data) {
try {
// Tried so
io.sockets.volatile.emit('attantion', data);
// And tried so
io.sockets.emit('attantion', data);
client.emit('attantion', data);
client.broadcast.emit('attantion', data );
} catch (e) {
console.log(e);
client.disconnect();
}
});
});
Client.js:
socket.emit("attantion", data);
socket.on('attantion', function (data) {
pushData(data);
});
See this post for different options for socket.io messages
Send response to all clients except sender (Socket.io)
io.sockets.on('connection', function (client) {
client.on('attantion', function (data) {
//client.emit('attantion', data ); // This will send it to only the client
//client.broadcast.emit('attantion', data); // This will send it to everyone but this client
io.emit('attantion', data); // This will send it to all attached sockets.
});
});
Edit
I wonder if this post can help you?
Socket.io - Cannot load file
I was curious how sending the php file to the client through node.js works? are you using another framework?
Could you show more of what your client code looks like? loading the lib and the instantiation of the socket.
Version 2 of post
Okay, first the file structure:
app
|___app.js
|___models/
|_user.js
|___routes/
|___admin.js
|___public/
|___js/
|___script.js
app.js:
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
http.listen(3000, function (err){
if (err) throw err;
console.log("Server is running");
});
script.js:
var socket = io();
//Next, this tells the browser that is has connected to the socket.io server
socket.on('connect', function() {
console.log('Connected to socket.io server!');
});
socket.on('message', function(message){
console.log('New message: ');
console.log(message.text);
});
var $newUsername = $('#Username');
$newUsername.on('blur', function(event){
socket.emit('message', {
text: $newUsername.val()
});
});
So on a registration page, if a user enters a 'username' already in the database, it will console.log 'This user already exists'. At least, that's the idea.
There is still sockets.io code I need to add on the server side. I am trying to put it here:
admin.js:
var router = require('express').Router();
var User = require('../models/user');
io.on('connection', function(socket) {
console.log('User connected via socket.io!');
socket.on('message', function(message) {
Username.findOne({username: message.text}, function (err, existingUsername) {
if (existingUsername) {
console.log('This user already exists: ' + message.text);
}
});
});
});
So, as this stands, the sockets.io code in admin.js won't work because it can't access the io function. I would like to know how I can fix this.
To add to this: The sockets.io code I have in the admin.js file will work fine if I placed it in my app.js file.
The key here is to pass the io instance to any module that needs it when that module is first loaded. This is called the "push" method of sharing as you share by pushing data from one module to another by passing it in the constructor function of the other module.
There is also a "pull" module where one module asks some other module for some shared data by calling a method in that module.
Here's how you could implement the "push" model:
In your admin.js file, you define a constructor function that you call and pass the io instance to when you load it:
var router = require('express').Router();
var User = require('../models/user');
var io;
// define constructor function that receives the io instance so the rest
// of the module can use it
module.exports = function(ioInstance) {
io = ioInstance;
io.on('connection', function(socket) {
console.log('User connected via socket.io!');
socket.on('message', function(message) {
Username.findOne({
username: message.text
}, function(err, existingUsername) {
if (existingUsername) {
console.log('This user already exists: ' + message.text);
}
});
});
});
}
Then, in your app.js file:
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
http.listen(3000, function (err){
if (err) throw err;
console.log("Server is running");
});
// when you load the admin.js file, you pass it the io instance
require('./routes/admin.js')(io);
Below are 2 answers. While both answers will technically work, it is advised that you do not use either of them. Use the answer provided above.
Answer 2
So my route files all have this:
var router = require('express').Router();
Now, in any of the route files where I need sockets.io I did this:
var http = require('http').Server(router);
var io = require('socket.io')(http);
And this got my sockets.io code working.
Answer 1
So to get sockets.io code working in my route files, I simply removed 'var' in front of my http and io variables.
I changed:
//Socket io config
var http = require('http').Server(app);
var io = require('socket.io')(http);
to this:
//Socket io config
http = require('http').Server(app);
io = require('socket.io')(http);
Now my sockets.io code in my route files work fine.
I'm trying out Websockets/Node.js/Socket.io/Express for the first time and I'm trying to create a simple chat program. Everything runs fine and I see both clients in my node termial.
But when I try to execute my socket.send(), I get an error in Firefox (socket.send is not a function). It doesn't complain about socket.connect() so I know the socket.io.js is loaded.
Here is my server code:
var sys = require('util');
var express = require('express');
var io = require('socket.io');
var app = express.createServer();
app.listen(8080);
app.use(express.static(__dirname));
app.get('/', function (req, res) {
res.render('index.html', {
title: 'Chat'
});
});
var socket = io.listen(app);
socket.on('connection', function (client) {
client.on('message', function (message) {
console.log("Message: " + JSON.stringify(data));
socket.broadcast(message);
});
client.on('disconnect', function () {});
});
My client code:
<script src="http://localhost:8080/socket.io/socket.io.js"></script>
var socket = new io.Socket("http://localhost:8080");
socket.connect();
Then I do some code to get the chat message and send it.
socket.send(JSON.stringify(values));
Explanations
You haven't initialized Socket.io correctly on the server-side and client-side.
Client Side
new io.Socket("http://localhost:8080"); doesn't give you the object that you want, you need new io.connect("http://localhost:8080");.
You need to wait until the client is connected to the server before sending a message.
Server side
socket is the object send back by Socket.IO, you need to use socket.sockets to have access to on.
To broadcast a message, you need to use the client object like this: client.broadcast.send()
The variable data doesn't exist on your broadcast. You probably mean message.
Solution
Server
var sys = require('util'),
express = require('express'),
io = require('socket.io'),
app = express.createServer();
app.listen(8080);
app.use(express.static(__dirname));
app.get('/', function (req, res) {
res.render('index.html', {
title: 'Chat'
});
});
var io = io.listen(app);
io.sockets.on('connection', function (client) {
client.on('message', function (message) {
console.log("Message: " + JSON.stringify(message));
client.broadcast.send(message);
});
client.on('disconnect', function () {});
});
Client
<script src="http://localhost:8080/socket.io/socket.io.js"></script>
<script>
var socket = new io.connect("http://localhost:8080"),
connected = false;
socket.on('connect', function () {
connected = true;
});
// Use this in your chat function.
if (connected) {
socket.send(JSON.stringify(values));
}
</script>
socket.broadcast(message); should be io.sockets.emit('key', message);
when you use the socket object passed in threw the connect event your only emitting information to that client, to emit to all clients you have to use io.sockets.emit().
also with socket.send(JSON.stringify(values)); I think you want to do socket.emit(namespace, data);
see my connection file from one of my projects here: https://github.com/AdminSpot/HangoutCanopy/blob/master/javascripts/connection.js
You have to wait for socket.io to connect on the client side
var socket = new io.Socket("http://localhost:8080");
socket.connect();
socket.on('connect', function() {
socket.emit('event', data);
});