I am not really sure how to send and receive data using socket.io rooms.
This is my client side code:
var socket = io('https://the.url');
socket.on('connect', function() {
console.log('Connected to the socket.');
});
socket.on("client5", function (data) {
console.log(data);
});
And this is my server side code
var app = require('express')();
var server = require('http').Server(app);
var https = require('https');
var fs = require('fs');
var bodyParser = require('body-parser');
var privateKey = fs.readFileSync('path/to/key', 'utf8');
var certificate = fs.readFileSync('path/to/key', 'utf8');
var credentials = {key: privateKey, cert: certificate};
var httpsServer = https.createServer(credentials, app);
var io = require('socket.io')(httpsServer);
// HTTP server listening on port
io.set('origins', '*:*');
io.sockets.on('connection', function (socket) {
});
httpsServer.listen(10000);
// Middle ware
app.use(bodyParser.urlencoded({ extended: true }));
// Route
app.post('/anything', function (req, res) {
io.emit('client5', req.body);
res.end();
});
And this works fine. But this is not using the rooms. This code will just emit data to "client5" socket and on the client side I am able to receive that data using socket.on("client5").
What I want to do is have a group of people that will be joining different rooms.
So user A, B and C will come in and be added to room "First Room" and users D, E and F will be added to "Second Room".
How can I send and receive data between rooms?
Related
Why does my socket.io webapplication keeps loading, i've implemented auth with certifications, but when i try to access localhost, it keeps loading. ive tried follow this doc, but dosent help:https://socket.io/docs/v3/client-initialization/
i dont get any error.
server.s
'use strict';
// Setup basic express server
var express = require('express');
var app = express();
var port = process.env.PORT || 4000;
var crypto = require('crypto');
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database('./data/db.sqlite');
const bcrypt = require('bcrypt');
const tls = require('tls');
var validator = require('validator');
// Routing
app.use(express.static(__dirname + '/public'));
app.use(express.json());
// Chatroom
// usernames which are currently connected to the chat
var usernames = {};
var numUsers = 0;
const fs = require("fs");
const server = require("https").createServer({
cert: fs.readFileSync("./server-cert.pem"),
key: fs.readFileSync("./server-key.pem")
});
server.listen(port, function () {
console.log('Server listening at port %d', port);
});
const io = require("socket.io")(server);
io.on('connection', function (socket) {
console.log("works")
}
client.js
const fs = require("fs");
const socket = require("socket.io-client")(4000, {
ca: fs.readFileSync("./server-cert.pem")
});
socket.on("connect_error", (err) => {
console.log(`connect_error due to ${err.message}`);
});
Scenario: Creating a Node API (GET) calling that API in socket.io Node server and calling this socket server in angular client.
What i have done: Created a node API for get request and post and created a socket server I tried to consume the app.
Issues: 1. I tried to consume the API but was unable to get the data in the socket server and 2. If it works, also how can i get the socket data on button click in angular application?
Note: I'm running Node API on 3000 server and running socket server on 3001.
Below is my code
Node api code runnning on 3000 port:
const express = require('express')
const bodyParser = require('body-parser');
const cors = require('cors');
const app = express()
const port = 3000
let books = [{
"isbn": "9781593275846",
"title": "Eloquent JavaScript, Second Edition",
"author": "Marijn Haverbeke",
"publish_date": "2014-12-14",
"publisher": "No Starch Press",
"numOfPages": 472,
}];
app.use(cors());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.post('/book', (req, res) => {
const book = req.body;
// output the book to the console for debugging
console.log(book);
books.push(book);
res.send('Book is added to the database');
});
app.get('/book', (req, res) => {
res.json(books);
});
app.listen(port, () => console.log(`Hello world app listening on port ${port}!`));
Socket .io server running on 3001
var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http);
const apiUrl="http://localhost:3000/book"
io.on('connection', function (socket) {
socket.on('getBanners', function(data){
request.get(apiUrl,function (error, response, body){
console.log(body)
socket.emit('result', {res:JSON.parse(body)})
})
});
});
http.listen(3001, function(){
console.log('listening on *:3001');
});
Note: Node API server --> socketio server (not client)
I wouldn't recommend going by that design you have.
Unless there is a very specific/important reason to have the socket.io server on a different port than the HTTP server, I would recommend having your socket.io server upgraded from the HTTP server itself.
eg.
In bin/www:
const { initSocketIOServer } = require('../socket-server');
const port = normalizePort(process.env.PORT || '3001');
app.set('port', port);
/**
* Create HTTP server.
*/
const server = http.createServer(app);
initSocketIOServer(server);
In socket.server.js
module.exports.initSocketServer = (server) => {
io = require('socket.io')(server);
io.on('connection', (socket) => {
console.log('client connected');
socket.on('getBanners', (event) => {
// handle getBanners event here
});
});
};
However, going by your example, if you really need to make a request to the HTTP server to fetch data, you might want to use the HTTP library:
socket.on('getBanners', (event) => {
http.get({
hostname: 'localhost',
port: 3000,
path: '/book',
agent: false // Create a new agent just for this one request
}, (res) => {
// Do stuff with response, eg.
const socketResponse = processBooks(book);
socket.emit('result', socketResponse);
});
});
You can use any node package for requests like request https://github.com/request/request
here
I am trying to use the socket-anti-spam module (https://github.com/michaeldegroot/socket-anti-spam) in my web application. However, when I try using it, I get the following error:
Error: listen EADDRINUSE :::3000
Below is my code:
var express = require("express");
var socket = require("socket.io");
var socketListen = socket.listen(3000);
var bodyParser = require('body-parser');
var cors = require('cors');
var SocketAntiSpam = require("socket-anti-spam");
require('dotenv').config({ path: 'variable.env' });
// Initialize Node.JS application
var app = express();
var server = app.listen(process.env.PORT || 3000);
app.use(express.static("public", {
dotfiles: 'allow'
}));
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
const socketAntiSpam = new SocketAntiSpam({
banTime: 30, // Ban time in minutes
kickThreshold: 2, // User gets kicked after this many spam score
kickTimesBeforeBan: 1, // User gets banned after this many kicks
banning: true, // Uses temp IP banning after kickTimesBeforeBan
io: socketListen, // Bind the socket.io variable
});
You are trying to listen on the same port (3000) twice that’s why you are getting “Address In Use” error.
Try something like:
const SocketAntiSpam = require('socket-anti-spam')
const app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
const listen = server.listen(3000);
const socketAntiSpam = new SocketAntiSpam({
banTime: 30,
kickThreshold: 2,
kickTimesBeforeBan: 1,
banning: true,
io: io,
})
io.on('connection', function(socket){
console.log('a user connected');
socket.on('spam', (data) => {
console.log(data);
})
});
app.get('/hello', (request, response) => {
response.send('ok');
});
I'm trying to use io.sockets.on inside a route in a Node.js and Express app. I have been following what is said here: https://stackoverflow.com/a/31277123/8271839
I can successfully send io.sockets.emit events, but I cannot receive events with io.sockets.on.
Here is my code:
index.js:
const cors = require('cors');
const express = require('express');
const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server);
const taskRequest = require('./routes/taskRequest');
app.use(cors())
app.use(express.json());
app.use('/api/taskRequest', taskRequest);
app.set('socketio', io);
server.listen(4002);
io.sockets.on("connection",function(socket){
console.log("connected");
socket.on("connected", function (data) {
console.log("hello");
})
});
routes/taskRequest.js:
const express = require('express');
const router = express.Router();
router.post('/', async (req, res) => {
var io = req.app.get('socketio');
//pickedUser is one of the connected client
var pickedUser = "JZLpeA4pBECwbc5IAAAA";
//we only send the emit event to the pickedUser
io.to(pickedUser).emit('taskRequest', req.body);
io.on('connection', function (socket) {
console.log('connected 2');
socket.on('taskResponse', function () {
console.log('hello 2');
});
});
});
module.exports = router;
When a client is connected, I get the "connected" message in console, but not the "connected 2" message.
Also, when client emits "connected" message, I get "hello" in console, but when clients emits "taskResponse" message, I don't get "hello 2" in console.
Though when io.to(pickedUser).emit('taskRequest', req.body); is called, it works, client receives the "taskRequest" message.
Why is .emit() working inside my route but not .on() ?
According to you code, io is a Socket.IO server instance attached to an instance of http.Server listening for incoming events. Then inside the route you are again attaching a instance to listen to to incoming events which does not work. the io.to(pickedUser).emit works because the server instance with socketio is correctly listening to the connection thus giving the console.log("connected");.
index.js:
const cors = require('cors');
const express = require('express');
const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server);
const taskRequest = require('./routes/taskRequest');
app.use(cors())
app.use(express.json());
app.use('/api/taskRequest', taskRequest);
app.set('socketio', io);
server.listen(4002);
routes/taskRequest.js:
const express = require('express');
const router = express.Router();
router.post('/', async (req, res) => {
var io = req.app.get('socketio');
//pickedUser is one of the connected client
var pickedUser = "JZLpeA4pBECwbc5IAAAA";
io.on('connection', function (socket) {
console.log('connected 2');
io.to(pickedUser).emit('taskRequest', req.body);
socket.on('taskResponse', function () {
console.log('hello 2');
});
});
});
module.exports = router;
I mark TRomesh answer as the right answer, since indeed you can only have one io.on('connection', function (socket) {}) in your code.
Now here is what I have done to make it work for me: the issue was that if you place io.on('connection', function (socket) {}) within your router.post('/', async (req, res) => {}), it will only be triggered when you call your endpoint. In my case, I had some sockets events that I wanted to be called at anytime, not only when the endpoint is called. So I had to place the io.on('connection', function (socket) {}) outside of my router.post('/', async (req, res) => {}). Thus I couldn't use var io = req.app.get('socketio'); inside the router. Here is what I have done instead:
index.js:
const cors = require('cors');
const express = require('express');
const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server);
const taskRequest = require('./routes/taskRequest')(io);
app.use(cors())
app.use(express.json());
app.use('/api/taskRequest', taskRequest);
server.listen(4002);
routes/taskRequest.js
const express = require('express');
const router = express.Router();
module.exports = function(io) {
//we define the variables
var sendResponse = function () {};
io.sockets.on("connection",function(socket){
// Everytime a client logs in, display a connected message
console.log("Server-Client Connected!");
socket.on('connected', function(data) {
//listen to event at anytime (not only when endpoint is called)
//execute some code here
});
socket.on('taskResponse', data => {
//calling a function which is inside the router so we can send a res back
sendResponse(data);
})
});
router.post('/', async (req, res) => {
//pickedUser is one of the connected client
var pickedUser = "JZLpeA4pBECwbc5IAAAA";
io.to(pickedUser).emit('taskRequest', req.body);
sendResponse = function (data) {
return res.status(200).json({"text": "Success", "response": data.data});
}
});
return router;
};
I have created an HTTPS server with socket.io and a client with socket.io-client.
Problem is that apparently socket.io-client does not check validity of HTTPS connection by the given CA in it's option.
For clarification here's a sample code: In simple https request if I do not provide CA in client I get Error: unable to verify the first certificate, but with socket.io-client connection establishes, which is totally not what I want.
//Client
var https = require('https'),
socketClient = require('socket.io-client'),
fs = require('fs');
var options = {
// IT'S EXPECTED THAT I DON'T PROVIED CA, HTTPS CONNECTION FAILS
//ca: fs.readFileSync('cert/ca.crt'),
agent: false
};
var socket = socketClient('https://localhost', options);
socket.on('connect', function() {
console.log('Connected to hub');
socket.emit('msg', function(resp){
console.log('Response: ' + resp);
});
});
And server :
// Server
var https = require('https'),
socketIo = require('socket.io'),
fs = require('fs');
var options = {
// CERTIFICATE HAS BEEN SIGNED WITH CA
cert: fs.readFileSync('cert/signed.crt'),
key: fs.readFileSync('cert/signed.key'),
rejectUnauthorized: false
};
var app = https.createServer(options, function(req, res) {
res.end('Hi');
});
var io = socketIo(app);
io.on('connection', function(socket) {
console.log('Connected !');
socket.on('msg', function(cb) {
console.log('Msg recved');
cb('Client got it');
});
});
app.listen(443, function() {
console.log('Server Started ...');
});