I am using socket.io in a react - node project. I have a problem with the socket not refreshing when the page refreshes.
It works first as the server and the react dev server run for the first time. After using the socket ( emitting something from the server ), refreshing the browser page would result in an error in the web socket.js file :
WebSocket connection to
'ws://localhost:4000/socket.io/?EIO=3&transport=websocket&sid=XTE63CeWdp676cRXAAAF'
failed: Error during WebSocket handshake: Unexpected response code:
400
here is the code I use in client and server :
SERVER :
const express = require('express');
const socketconfig = require('./socket.io');
class Server {
constructor({ config, router, logger, }) {
this.config = config;
this.logger = logger;
this.express = express();
this.express.disable('x-powered-by');
this.express.use(router);
}
start() {
return new Promise((resolve) => {
const http = this.express
.listen(this.config.web.port, () => {
const { port } = http.address();
this.logger.info(`[p ${process.pid}] Listening at port ${port}`);
resolve();
});
var io = require('socket.io').listen(http,function () {
console.log("I AM CONNECTIONG")
});
this.freshio=io.sockets;
socketconfig.setOnConnection(this.freshio, ()=>{
console.log('Connexion COnditions are set');
});
socketconfig.setOnDisconnect(this.freshio, ()=>{
console.log('client disconnected');
});
this.clients = socketconfig.clients;
});
}
}
module.exports = Server;
the start() method would be called when the server is initiated.
the socketConfig file is just a toolkit for saving clients and setting conditions, it doesn't interfere with anything.
CLIENT :
import openSocket from 'socket.io-client';
let url = Store.config.socketserverurl + ":" + Store.config.socketserverport;
const socket = openSocket.connect(url);
Store is just the flux store that has the config files linked to it.
I have tried adding the webSockets method of using socket.io instead of the http method but that was in vain as an other problem spiraled.
what should I do ?
Related
i have a node backend using socket io
first in app.js initialize te app
const express = require("express")
const app = express()
module.exports = {
app,
express
}
then in io.js, i create the socket server
const { app } = require("./app");
const http = require("http");
const socketio = require("socket.io");
const server = http.createServer(app);
const io = socketio(server);
module.exports = io;
then in the server.js first i import the app.js for api calls then i import io.js
require("dotenv").config();
const { app, express } = require("./app");
const logger = require("./logger");
const io = require("./io");
then i simply add emit listen code in the server.js
io.on("connection", (socket) => {
console.log("we have a new connection");
socket.on("disconnect", () => {
console.log("the socket disconnected");
});
socket.on("join", ({ user_id }, callback) => {
// const notification = getListNotifications(user_id);
// const popup = getUserPopup(user_id);
// socket.emit("nofication", { popup: popup.count, notification });
socket.emit("nofication", { popup: 3, notificaton: { a: 1 } });
socket.join(user.room);
callback();
});
then i run the server.js file in dev mode nodemon server.js
Then in react i simply use socket.io
import io from "socket.io-client";
useEffect(() => {
socket = io("ws://localhost:3009", {
"force new connection": true,
reconnectionAttempts: "Infinity",
timeout: 10000,
transports: ["websocket"],
});
return () => {
socket.disconnect();
};
}, []);
it gives me this error in browser console
the server node.js console is receiving https protocol
i find out in other answers that it maybe some protocol issue.
happy to learn from you. Thanks in advance
Happened to me that i was listening the server with app.listen which only recieves https protocol....but i have created a seperated ws server with the server variable which should listen to a port so that the server can receive ws connection...
better to use this library npm link will make work much easier...
I'm trying to automatically refresh list when a change is happend in database. so far i'm getting this error in console reapeatedly
so can't find the bug.
app.js
//importing modules
const express = require('express');
const http = require('http');
const path = require('path');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const cors = require('cors');
const socketIO = require('socket.io');
const errorHandler = require('./_helpers/error-handler');
const app =express();
const notice = require('./controllers/noticeController');
const employee = require('./controllers/employeeController');
const users = require('./users/users.controller');
//connect mongoDb
//on connection
mongoose.connection.on('connected',()=>{
console.log('Connected to database');
});
mongoose.connection.on('error',(err)=>{
if(err){
console.log('Error in Database Connection '+err);
}
});
const port = 3000;
//adding middleware
app.use(cors());
//body-parser
app.use(bodyParser.json());
//routes
app.use('/api', notice);
app.use('/api', employee);
app.use('/users', require('./users/users.controller'));
app.use(errorHandler);
const server = http.createServer(app);
const io = socketIO(server);
app.set('io',io);
//static files
app.use(express.static(path.join(__dirname, 'public')));
app.listen(port,()=>{
console.log('Server started at port: '+port);
});
and here is the post and get API with socket.io
noticeController.js
//retrieving notice list
router.get('/notices/get',(req,res)=>{
notice.find({}).then((notices)=>{
res.send(notices)
});
});
//add notice
router.post('/notice/add',(req,res,next)=>{
const io = req.app.get('io');
let newNotice = new notice({
title : req.body.title,
description : req.body.description,
image : req.body.image
});
newNotice.save().then(()=>{
io.emit('newNoticeAdded');
});
});
so can anyone help with this matter?
to client side. I have use socket-io-client package.
ts file.
ngOnInit(): void {
this.socket.on('newNoticeAdded',()=>{
this.noticeService.getNotices()
.subscribe(notices => {
this.notices = notices;
});
});
}
notices is the list that want to update automatically on change.
Right away, I could spot something fishy with your code. Look at the following lines:
const server = http.createServer(app);
const io = socketIO(server);
app.set('io', io);
//static files
app.use(express.static(path.join(__dirname, 'public')));
app.listen(port, ()=>{
console.log('Server started at port: '+ port);
});
What is happening here? Well, let's analyze:
You are creating a HTTP using http.createServer(app), then,
You are passing the server to the socketIO() constructor, after that,
You set up some static file routes for your app, finally,
You call app.listen on your express app to start the express app.
What is missing here? You never called server.listen on your HTTP server!
Why is that important, you ask? Because your Socket.IO server is bound to your HTTP server, not your express app. Since you only told your express app to start accepting connections, your Socket.IO server hasn't been started.
To solve this, you could just call server.listen on your HTTP server instead of you express app, like this:
const server = http.createServer(app);
const io = socketIO(server);
app.set('io', io);
//static files
app.use(express.static(path.join(__dirname, 'public')));
// Notice we called the listen function on your HTTP server
// instead of your express app. Your express app will still work
// because you passed your app to the http.createServer method
server.listen(port, ()=>{
console.log('Server started at port: '+ port);
});
Oh, and also, you should make sure your client-side code is connecting to the correct address. Like, make sure you connect to the address that your server is listening on, not some other address. I'm saying this because your error pictures show that you were trying to connect to port 4200 instead of 3000, which is what your server is listening on.
EDIT Since I saw you weren't sure how to connect your client to the same port as your server is running on, here's some code to help you out.
// You could just do this, and the socket.io client
// will connect to the ```window.location```, which
// is usually what you want.
// This is good because you don't hard-code the URL
// into your code, making it easier for you to put the
// script into production.
const socket = io();
// You could also do ```io.connect```, but BEWARE,
// you have to change the URL that the socket.io client
// connects to manually, so that's why I prefer the above
// method.
const socket2 = io.connect("http://localhost:3000");
You can see the default behaviour of the io() function here
Hope this helps.
You need to use the same port on both sides. My client side typescript service (server is using port 8090):
import { Injectable } from '#angular/core';
// rxjs
import { Observable } from 'rxjs';
// other
import { NGXLogger } from 'ngx-logger';
import { Event } from '../model/event';
import { environment } from '../../../environments/environment';
import * as socketIo from 'socket.io-client';
export let SERVER: string = "";
if (environment.production) {
SERVER = 'http://10.1.1.7:8090'; // EDS Server
} else {
SERVER = 'http://10.1.1.194:8090'; // Portalogic PC
//SERVER = "http://" + window.location.hostname + ":8090";
}
#Injectable({
providedIn: "root"
})
export class SocketService {
debug: boolean = true;
private socket: any;
constructor(
private logger: NGXLogger,
) { }
public initSocket(): void {
if (this.debug) {
this.logger.debug("initialize websocket at " + SERVER);
}
this.socket = socketIo(SERVER);
}
public closeSocket(): void {
this.socket.close();
}
public sendEvent(event: Event, data?: Object): void {
if (this.debug) {
this.logger.debug("sendEvent >> event = " + event.toString() + "; data = " + JSON.stringify(data));
}
this.socket.emit(event.toString(), data);
}
public onEvent(event: Event): Observable<Event> {
return new Observable<Event>(observer => {
this.socket.on(event, (data: any) => observer.next(data));
});
}
}
I call initIoConnection from app.component.ts then subscribe to onEvent events.
I have initialized WebSocket on my backend.
Then use rxjs/webSocket to connect and receive the following error on the browser:
connection to 'ws://localhost:3000/' failed: Connection closed before receiving a handshake response
server.js related code:
const { app, onServerInitialized } = require('./app');
const port = normalizePort(process.env.PORT);
console.log('Server is running on port ' + process.env.PORT);
app.set('port', port);
const server = http.createServer(app);
onServerInitialized(server);
app.js related code:
const app = express();
const onServerInitialized = server => {
const io = socketio(server);
io.on('connection', socket => {
console.log('subscrie');
});
};
module.exports = { app, onServerInitialized };
WebSocketService
import { webSocket, WebSocketSubject } from 'rxjs/webSocket';
export class WebSocketService {
private ws$: WebSocketSubject<any> = webSocket('ws://localhost:3000');
public getWSListener() {
return this.ws$.asObservable().pipe();
}
public sendMessage(message: string) {
this.ws$.next({ message });
}
}
app.component.ts
constructor(
private webSocketService: WebSocketService,
) {}
ngOnInit() {
this.webSocketService.getWSListener().subscribe(() => {
console.log('event')
});
}
You are using socket.io package, and this package has server setted up at /socket.io path. So try this uri: ws://localhost:3000/socket.io/?EIO=3&transport=websocket
Also make sure that in onServerInitialized function you don't need to add this line at the bottom
io.listen(+process.env.PORT);
EDIT:
Better use ngx-socket-io package into Angular project
I am using nodeJs as backend and reactJs as my frontend the thing is I emitted a socket emit function from node
var server = require('http').createServer();
var io = require('socket.io')(server);
io.emit('quantity_check', 'KR')
now the issue is I'm unable to catch the emit
let serverUrl = 'localhost:3008'
const socket = socketIOClient(serverUrl);
socket.on("quantity_check", data => this.setState({ kiiii: data }));`
const socket = socketIOClient(serverUrl);
I'm checking this locally even i tried with my ip its not connecting I am not sure where the issue occurs
pc:nodejs and reactjs running on different ports
Can you post the code of you node server file and the react file where are you are listening to the sockets?. Anyway i hope that emit event is inside the connection
io.on('connection', function(socket) {
io.emit('quantity_check', 'KR')
}
and did you use the life cycle method componentDidMount to receive message
componentDidMount() {
socket.on("quantity_check", data => {
console.log(data);
});
}
Try something like this.
server
const server = require('http').createServer();
const io = require('socket.io')(server);
io.on('connect', (socket) => {
io.emit('quantity_check', 'KR');
});
Client(React side)
import io from 'socket.io-client';
const socket = io('http://localhost:3008');
export class App extends Component {
componentDidMount() {
socket.on('connect', () => {
console.log(socket.connected);
});
socket.on("quantity_checke", data => {
console.log(data);
});
}
render().......
}
I am using SocketIo with Nodejs, Express server and MongoDB, I followed the documentation . it works fine when connecting multiple clients they can send messages to each other without any problem . when I made an Http request, I cannot connect any new clients and get this error.
socket.io.js:7370 WebSocket connection to
'ws://localhost:28232/socket.io/?userId=userAmr&EIO=3&transport=websocket&sid=wNTTgrUD-PSeNaIcAAAF'
failed: Error during WebSocket handshake: Unexpected response code:
400
the other connected users before the Http request can continue sending messages without any problem.
I debugged the Socket library and found the client socket request go to connect function then fire errorCode:1
This this my code
/**
* Create Express server.
*/
const app = express();
// API endpoint
app.get('/api/test',(req,res)=>{
res.status(200).send({test:"test"});
});
/**
* Init socket
*/
// the following line not working too
// const server = require('http').createServer(app);
const server = require('http').Server(app);
const io = require('socket.io')(server);
io.on('connection', (socket) => {
// emit message to group
socket.on('emitMessage', (data) => {
io.emit('emitMessage', data);
});
});
The Client side code
import { Injectable } from '#angular/core';
import * as io from "socket.io-client/dist/socket.io.js"
import { BehaviorSubject } from 'rxjs';
#Injectable()
export class AppSocketService {
private url = 'http://localhost:28232';
private socket;
constructor() {
}
connect(){
this.socket = io(this.url,{
query:{userid:"123"},
forceNew:true,
'force new connection': true,
autoConnect: true,
reconnectionDelay: 1000,
timeout: 100000,
reconnectionDelayMax: 5000,});
this.socket.on('connect', () => {
console.log("connect",{"socketId":this.socket.id});
this.startListening();
});
}
startListening(){
this.socket.on('emitMessage', (data) => {
console.log(data);
});
}
emitMessage(message){
this.socket.emit('emitMessage', {message});
}
}
Client version:"socket.io-client": "^1.7.3"
Server version: "socket.io": "^1.7.3"
i found the problem, the package express-status-monitor making this wrong behavior .
try to remove it, and it will work perfectly
// comment these lines, as they making the issue
// const expressStatusMonitor = require('express-status-monitor');
// app.use(expressStatusMonitor());
The final code:
let app = require('express')();
// these two lines were making the problem, please comment them. if you want to reproduce the problem enable them again
// const expressStatusMonitor = require('express-status-monitor');
// app.use(expressStatusMonitor());
let http = require('http').Server(app);
let io = require('socket.io')(http);
let port = process.env.PORT || 3000;
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
app.get('/api/v0/availabilities',(req,res)=>{
res.status(200).send({test:"test"});
});
io.on('connection', (socket) => {
// emit message to group
socket.on('emitMessage', (data) => {
io.emit('emitMessage', data);
});
});
http.listen(port, function(){
console.log('listening on *:' + port);
});