Hooking up a websocket to AWS Elastic Beanstalk - node.js

I'm having an issue with connecting my websocket on port 7777 to my aws deployment. I am new to sockets and deployment. I have my main port 8081 hooked up, but having issues with the websocket. I've been at this for a day and would like some pointers! Thanks!
Currently, receiving this error:
React code
import React from 'react';
import openSocket from 'socket.io-client';
let socket = openSocket('http://my-api.us-east-2.elasticbeanstalk.com:7777', { transports: ['websocket'] });
export class HomePage extends React.Component {
state = {
channels: null,
channelSelected: false,
socket: null,
typers: {},
channel: 1,
messages: [],
msg: ''
}
socket;
componentDidMount() {
}
componentDidUpdate() {
if (this.props.username && !this.state.channelSelected) {
this.configureSocket();
this.setState({ channel: 1, channelSelected: true });
this.socket.emit('joinChannel', { channel: 1, username: this.props.username });
}
}
configureSocket = () => {
socket.on('connection', () => {
if (this.state.channel) {
this.handleChannelSelect(this.state.channel.id);
}
});
socket.on('incomingChat', username => {
let typers = this.state.typers;
if (!typers[username]) {
typers[username] = 1;
this.setState({ typers })
}
});
socket.on('clearingChat', username => {
let typers = this.state.typers;
delete typers[username]
this.setState({ typers });
});
socket.on('incomingMessage', details => {
let messages = this.state.messages;
let typers = this.state.typers;
delete typers[details.username]
messages.push(details);
this.setState({ messages, typers });
})
socket.on('channel', channel => {
let channels = this.state.channels;
channels.forEach(c => {
if (c.id === channel.id) {
c.participants = channel.participants;
}
});
this.setState({ channels });
});
socket.on('message', message => {
let channels = this.state.channels
channels.forEach(c => {
if (c.id === message.channel_id) {
if (!c.messages) {
c.messages = [message];
} else {
c.messages.push(message);
}
}
});
this.setState({ channels });
});
this.socket = socket;
}
handleChannelSelect = e => {
e.preventDefault();
this.setState({ channel: 1 });
this.socket.emit('leaveChannel', this.props.username);
}
handleSendMessage = e => {
e.preventDefault();
this.socket.emit('send-message', { msg: this.state.msg, username: this.props.username, channel: this.state.channel });
this.setState({ msg: '' });
}
handleChange = e => {
const { value } = e.target;
this.setState({ msg: value });
if (!value) this.socket.emit('addingMessage', { username: this.props.username, msg: 'cleared' });
if(value) this.socket.emit('addingMessage', { username: this.props.username, msg: value });
}
render() {
return (
<div className='chat-app'>
<form onSubmit={this.handleSendMessage}>
<input type="text" onChange={this.handleChange} value={this.state.msg} />
</form>
<button onClick={this.handleChannelSelect}></button>
{ this.state.messages.length > 0 && this.state.messages.map(({ username, msg }) => <p key={Math.random()}>{`${username}: ${msg}`}</p>) }
{Object.keys(this.state.typers).length > 0 && Object.keys(this.state.typers).map(el => el !== this.props.username && <p>{`${el} typing....`}</p>)}
</div>
);
}
}
server code
const app = require("./app");
const socketio = require('socket.io');
const express = require('express');
const http = require('http');
const db = require("./db");
const AWS = require("aws-sdk");
const CryptoJS = require("crypto-js");
const em = express();
const server = http.createServer(em);
const chatPort = process.env.LIVE_CHAT_PORT || 7777;
const io = socketio(server);
server.listen(chatPort, () => {
console.log(`Live Chat sock running on port ${chatPort}`)
});
app.listen(process.env.PORT || 8081, () => {
console.log("Listening on PORT 8081");
});
io.on('connection', socket => {
let user;
socket.on('joinChannel', async ({ username, channel }) => {
user = userJoin(socket.id, username, channel);
socket.on('addingMessage', details => {
const { username, msg } = details;
if (msg === 'cleared') {
io.to(user.room).emit('clearingChat', username);
} else {
io.to(user.room).emit('incomingChat', username);
}
})
socket.join(user.room);
});
socket.on('send-message', async details => {
const { msg, username, channel } = details;
let em = await db.query(`
INSERT INTO messages(conversation_id, user_id, shared_post, message, posted)
VALUES($1, $2, null, $3, current_timestamp)
RETURNING id;
`, [channel, username, msg])
io.to(user.room).emit('incomingMessage', details)
})
socket.on('leaveChannel', username => {
const user = userLeave(username);
socket.disconnect();
});
});

Related

Even if peer connection is establish but not getting the remote stream?

import React, { useEffect, useContext, useRef } from 'react';
import { SocketContext } from "../../contexts/socketContext";
const Call = ({ myId, otherId, init }) => {
const socket = useContext(SocketContext);
const localStream = useRef();
const remoteStream = useRef();
const _pc = useRef(new RTCPeerConnection());
useEffect(() => {
navigator.mediaDevices.getUserMedia({ audio: true, video: true }).then((stream) => {
localStream.current.srcObject = stream;
stream.getTracks().forEach((track) => {
_pc.current.addTrack(track, stream);
});
}).catch((err) => {
console.log(err);
});
if (init) {
createAndSendOffer()
}
_pc.current.onicecandidate = (e) => {
if (e.candidate) {
socket.emit("candidate", { from: myId, to: otherId, candidate: e.candidate });
}
}
_pc.current.ontrack = (e) => {
console.log("Hello");
if (e.streams) {
console.log(e.streams);
}
}
});
useEffect(() => {
socket.on("offer", (data) => {
createAndSendAnswer(data);
});
socket.on("answer", (data) => {
setAnswer(data.answer);
});
socket.on("candidate", (data) => {
_pc.current.addIceCandidate(new RTCIceCandidate(data.candidate));
});
});
async function setAnswer(answer) {
_pc.current.setRemoteDescription(new RTCSessionDescription(answer));
}
async function createAndSendOffer() {
const offer = await _pc.current.createOffer({ offerToReceiveAudio: true, offerToReceiveVideo: true });
socket.emit("offer", { from: myId, to: otherId, offer });
_pc.current.setLocalDescription(new RTCSessionDescription(offer));
}
async function createAndSendAnswer({ from, to, offer }) {
_pc.current.setRemoteDescription(new RTCSessionDescription(offer));
const answer = await _pc.current.createAnswer();
_pc.current.setLocalDescription(new RTCSessionDescription(answer));
socket.emit("answer", { from: myId, to: otherId, answer });
}
return (
<div>
<video autoPlay muted ref={localStream} />
<video autoPlay muted ref={remoteStream} />
</div>
)
}
export default Call
``
I am trying to make a video calling app but remote peer video is not getting.

I can send message to socket server and its print the output but can't recieve from the socket server to client in nodejs

I am Creating a chat application everything is almost done I can send messages and the server is receiving the data but can't receive the data from the socket.io server
basically, I created a separate server that connects the clients it didn't connect to the database. I tried everything but couldn't help
SocketServer.js
const io = require('socket.io')(9739, {
cors: {
origin: "*",
}
})
let activeUsers = [];
io.on('connection', (socket) => {
console.log('New user connected');
socket.on('login', (data) => {
console.log(data);
if (!activeUsers.some((user) => user.id === data)) {
activeUsers.push({
id: data,
socketId: socket.id
});
}
// remove the active user that id is null
activeUsers = activeUsers.filter((user) => user.id !== null);
console.log(activeUsers);
io.emit('activeUsers', activeUsers);
});
socket.on("sendMessage",(data)=>{
const { receiverId } = data;
const receiver = activeUsers.find((user) => user.id === receiverId);
console.log("Sending Message to : ", receiver);
console.log(data);
if(receiver){
console.log("comming")
console.log(receiver.socketId);
// send message to the receiver
const RSocketId = receiver.socketId;
console.log("RSocketId", RSocketId);
io.to(RSocketId).emit("getMessage", {
data: data,
});
}
});
socket.on("end", () => {
console.log("end");
socket.disconnect();
});
socket.on('disconnect', () => {
console.log('User disconnected');
activeUsers = activeUsers.filter((user) => user.socketId !== socket.id);
console.log(activeUsers);
io.emit('activeUsers', activeUsers);
});
});
Client Side
import axios from "axios";
import React, { useRef } from "react";
import nookies from "nookies";
import Index from "./index";
import FriendsHolder from "../../components/Holders/FriendsHolder";
import FriendsDetails from "../../components/Holders/details-chats-holders/FriendsDetails";
import { useRouter } from "next/router";
import DmsComponent from "../../components/Holders/details-chats-holders/DmsComponent";
import { userDetails } from "../../libs/chats";
import SetUserName from "../../models/SetUserName";
import { io } from "socket.io-client";
const friends = ({ token }: any) => {
const router = useRouter();
const [isLoading, setIsLoading] = React.useState(false);
const [username, setusername] = React.useState(false);
const [sendMsg, setSendMsg] = React.useState(null);
const [receivedMsg, setReceivedMsg] = React.useState(null);
const socket = useRef<any>();
React.useEffect(() => {
const init = async () => {
const { data } = await userDetails(token);
if (
data &&
(data.data.username.length > 20 || data.data.username === "")
) {
setusername(true);
} else {
setusername(false);
socket.current = io("ws://localhost:9739");
socket?.current.emit("login", data.data?.id);
socket?.current.on("activeUsers", (users: any) => {
console.log("active users", users);
});
}
};
if (token) {
init();
}
}, []);
const handleLoading = () => {
setIsLoading(true);
};
const handleNotLoading = () => {
setIsLoading(false);
};
React.useEffect(() => {
handleNotLoading();
}, [isLoading]);
// Sending message through the socket server
React.useEffect(() => {
if (sendMsg !== null) {
socket.current?.emit("sendMessage", sendMsg);
}
}, [sendMsg]);
// Recieving Message through the socket server
React.useEffect(() => {
socket.current?.on("getMessage", (data: any) => {
setReceivedMsg(data);
});
}, []);
React.useEffect(() => {
console.log(receivedMsg);
}, [receivedMsg]);
return (
<Index>
{username ? (
<SetUserName />
) : (
<>
<FriendsHolder data={token} handleLoading={handleLoading} />
{router.asPath === "/app/friends" && <FriendsDetails token={token} />}
{router.asPath === `/app/friends?id=${router.query.id}` &&
!isLoading && (
<DmsComponent token={token} setSendMsg={setSendMsg} />
)}
</>
)}
</Index>
);
};
export default friends;
export const getServerSideProps = async (ctx: any) => {
const cookies = nookies.get(ctx);
const token = cookies.token;
if (!token) {
return {
redirect: {
destination: "/?login",
permanent: false,
},
};
}
return {
props: {
token: token || null,
},
};
};

Create private chat with MERN and Socketio

i want to send message to specific user from react-autocomplete dropdown menu with select and display that message in their own window. And also i am trying to save messages to my mongodb but when i check mongocompass server it is only showing me the _id and and when i click send button in front end it is sending same message multiple times .Here is what i have so far but it is sending the message to everyone. i need help to get my code right to create private chat with saving correctly to db and retrieve messages everytime page refreshes
CLIENT:
const [username, setUsername] = useState("");
const [onlineUsers, setOnlineUsers] = useState([]);
const [chatHistory, setChatHistory] = useState([]);
const ADDRESS = "http://localhost:1337";
const socket = io(ADDRESS, { transports: ["websocket"] });
useEffect(() => {
socket.on("connect", () => {
console.log("Connection established!");
});
socket.on("loggedIn", () => {
console.log("Successfully logged in");
fetchOnlineUsers();
});
socket.on("newConnection", () => {
console.log("Look! another client connected!");
fetchOnlineUsers();
});
socket.on("message", (newMessage) => {
console.log("new message received!", newMessage);
setChatHistory((currentChatHistory) => [
...currentChatHistory,
newMessage,
]);
});
}, []);
const handleSubmitMessage =(e)=> {
e.preventDefault();
const messageToSend = {
text: message,
sender: username,
id: socket.id,
timeStamp: Date.now()
}
socket.emit("sendmessage", messageToSend)
setChatHistory([...chatHistory, messageToSend])
setMessage("")
}
const handleOnSearch = (string, results) => {}
const handleOnHover = (result) => {}
const handleOnSelect = (item) => {
console.log("ITEM",item);
}
const handleOnFocus = () => {}
const formatResult = (item) => {
return (
<>
<span style={{ display: 'block', textAlign: 'left' }}>{item.username}</span>
</>
)
}
SERVER CODE
import express from "express";
import cors from "cors";
import mongoose from "mongoose";
import listEndpoints from "express-list-endpoints";
import { Server } from "socket.io";
import { createServer } from "http";
import MsgModel from './db/schema.js'
const { MONGO_URL } = process.env;
const app = express();
app.use(cors());
app.use(express.json());
const server = createServer(app);
const io = new Server(server);
const port = process.env.PORT || 1337;
let onlineUsers = [];
io.on("connect", (socket) => {
socket.join("main-room")
socket.on("setUsername", ({ username }) => {
onlineUsers = onlineUsers
.filter((user) => user.username !== username)
.concat({
username: username,
id: socket.id,
});
socket.emit("loggedIn");
socket.broadcast.emit("newConnection");
});
socket.on("sendmessage", (msg) => {
console.log("sendmessage",msg);
const saveMessageToDb = new MsgModel({msg:msg})
saveMessageToDb.save().then(()=> {
socket.to("main-room").emit("message", msg)
})
})
app.get("/online-users", (req, res) => {
res.send({ onlineUsers });
});
MONGOOSE SCHEMA
import mongoose from "mongoose";
const { Schema, model } = mongoose;
const msgSchema = new Schema(
{
msg: { type: String },
},
{ typeKey: '$type' }
);
export default model("Message", msgSchema);

Browsers hangs while using Socket.io with ReactJS and ExpressJS

Problem:
I am working on a chat application. When I send more than 9-10 requests, the browser slows down and eventually, it just hangs. On refreshing the page, everything is back to normal.
I searched the socket.io documentation but couldn't get any solution regarding this matter.
Code:
Here is my Backend Express.JS code:
index.js
const express = require("express");
const { addUser, getUser, deleteUser, getAllUsers } = require("./users_api");
const app = express();
const server = require("http").createServer(app);
const io = require("socket.io")(server, {
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST"],
},
});
const port = 5000 || process.env.PORT;
io.on("connection", (socket) => {
socket.on("join", ({ name, room }, callback) => {
const { err, user } = addUser({ id: socket.id, name, room });
if (err) return callback(err);
if (user) {
socket.emit("message", {
user: "admin",
text: `${user.name} has entered the room ${user.room}.`,
});
socket.broadcast.to(user.room).emit("message", {
user: "admin",
text: `${user.name} has joined the room.`,
});
socket.join(user.room);
io.to(user.room).emit("users", {
room: user.room,
users: getAllUsers(user.room),
});
callback();
}
});
socket.on("client_message", (msg) => {
const user = getUser(socket.id);
if (user) io.to(user.room).emit("message", { user: user.name, text: msg });
});
socket.on("disconnect", () => {
console.log(6);
const user = deleteUser(socket.id);
if (user) {
io.to(user.room).emit("message", {
user: "admin",
text: `${user.name} has left the room.`,
});
io.to(user.room).emit("users", {
room: user.room,
users: getAllUsers(user.room),
});
}
});
});
server.listen(port, () => console.log(`Server started at port ${port}.`));
users_api.js:
const current_users = [];
const addUser = ({ id, name, room }) => {
name = name.trim().toLowerCase().split(" ").join("_");
room = room.trim().toLowerCase();
const exist_user = current_users.find(
(user) => name === user.name && room === user.room
);
if (exist_user)
return {
err: "User with this name already exists.",
};
current_users.push({ id, name, room });
return { user: { id, name, room } };
};
const deleteUser = (id) => {
const index = current_users.findIndex((user) => user.id === id);
if (index !== -1) return current_users.splice(index, 1)[0];
};
const getUser = (id) => current_users.find((user) => user.id === id);
const getAllUsers = (room) =>
current_users.filter((user) => user.room === room);
module.exports = { addUser, deleteUser, getUser, getAllUsers };
Front-end Code:
import io from "socket.io-client";
import React, { useEffect, useRef, useState } from "react";
import queryString from "query-string";
import "./ChatPage.css";
const END_POINT = "http://localhost:5000";
const ChatPage = (props) => {
const [message, setMessage] = useState("");
const [messages, setMessages] = useState([]);
const [users, setUsers] = useState([]);
const socket = useRef(null);
const handleSubmit = () => {
socket.current.emit("client_message", message);
setMessage("");
};
useEffect(() => {
const { name, room } = queryString.parse(props.location.search);
socket.current = io(END_POINT);
socket.current.emit("join", { name, room }, (error) => {
if (error) alert(error);
});
return () => {
socket.current.disconnect();
socket.current.off();
};
}, [props.location.search, END_POINT]);
useEffect(() => {
socket.current.on("message", (msg) => {
setMessages([...messages, msg]);
});
socket.current.on("users", ({ users }) => {
setUsers(users);
});
}, [messages.length]);
return (
<div className="chat-room-container">
<div className="chat-room-left">
<ul>
{messages.map((message, i) => (
<li key={i}>
{message.name}
{message.text}
</li>
))}
</ul>
<input
type="text"
value={message}
onChange={(e) => setMessage(e.target.value)}
/>
<button type="button" onClick={handleSubmit}>
Submit
</button>
</div>
<div className="chat-room-right">
<ul>
{users.map((user, i) => (
<li key={i}>{user.name}</li>
))}
</ul>
</div>
</div>
);
};
export default ChatPage;
I don't understand what's wrong, please help.
Instead of sending a message on event or broadcast try to send list of messages to particular user or all users list with their messages belonging to same room. This will leads to less render in frontend.
For example,
Your Frontend code will change like,
useEffect(() => {
socket.current.on("message", (msgList) => {
setMessages(msgList);
});
socket.current.on("users", ({ users }) => {
setUsers(users);
});
}, [messages.length]);
Also if different rooms then there occurs a problem to filter the messages. So to solve this there are two possible ways:
When you send filter data from server.
Filter data in client according to user name and room name.
As this solution is not a good practice as every time the whole list of message will come and applying filter on that will increase time complexity. But you can reduce to some extent by making proper structure of data state on server.
I think this will help you.
You are creating new socket connection on every useEffect, so after ten messages, you have ten connections.
socket = io(END_POINT);
I store the created socket connection in useRef - so if it is created again, it is overwritten with the new one - and it does not duplicate.
const socketConection = useRef(null)
useEffect(() => {
socketConnection.current = io(END_POINT)
}, [deps])
Of course, in all following uses you have to use socketConection.current

NestJS Socket.Io left room but still receiving messages

I have three rooms General, TypeScript and Nest. I'am joining General room in the first and second browser tab. When I decide to leave General from the second tab and join TypeScript room I still get the messages from General even though I should have left it. The bug occures when you switch to room that has been in use by other client and leave it. I'am using NodeJs, Socket.io, NestJS and React.
Server
#WebSocketGateway()
export class ChatGateway implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect {
#WebSocketServer() server: Server;
private logger: Logger = new Logger('ChatGateway');
#SubscribeMessage('msgToServer')
handleMessage(client: Socket, message: { sender: string, room: string, message: string }): void {
this.server.to(message.room).emit('msgToClient', message);
this.logger.log(`msgToClient: ${message}`);
}
#SubscribeMessage('joinRoom')
handleRoomJoin(client: Socket, room: string ) {
client.join(room);
client.emit('joinedRoom', room);
this.logger.log(`Client joined ${room}`);
}
afterInit(server: Server) {
this.logger.log('Init');
}
handleDisconnect(client: Socket) {
this.logger.log(`Client disconnected: ${client.id}`);
}
handleConnection(client: Socket, ...args: any[]) {
this.logger.log(`Client connected: ${client.id}`);
}
#SubscribeMessage('leaveRoom')
handleRoomLeave(client: Socket, room: string ) {
console.log(client.id);
/* console.log(client.rooms);
console.log(client.adapter.rooms); */
client.leave(room);
/* console.log(room); */
/* client.rooms = {};
delete client.adapter.rooms[room]; */
client.emit('leftRoom', room);
this.logger.log(`Client left ${room}`);
/* console.log(client.adapter.rooms);
console.log(client.rooms); */
// console.log(client.adapter.rooms)
}
}
Client
const [state, setState] = useState({ sender: "", room: "", message: "" });
const [chat, setChat] = useState([
{ sender: "Peter", room: "General", message: "test" },
]);
const socket = io(BASE_URL);
const [room, setRoom] = useState({
General: false,
TypeScript: false,
NestJS: false,
});
console.log(room);
useEffect(() => {
socket.on("msgToClient", (msg) => {
setChat([...chat, { ...msg }]);
});
});
const onTextChange = (e) => {
setState({ ...state, [e.target.name]: e.target.value });
};
const onMessageSubmit = (e) => {
e.preventDefault();
const { sender, room, message } = state;
socket.emit("msgToServer", { sender, room, message });
setState({ message: "", sender: "", room: "" });
};
const toggleRoomMembership = (chatroom) => {
const isMemberOfActiveRoom = (chatroom) => {
return room[chatroom];
};
if (isMemberOfActiveRoom(chatroom)) {
setRoom({ ...room, [chatroom]: false });
socket.emit("leaveRoom", chatroom);
} else {
setRoom({ ...room, [chatroom]: true });
socket.emit("joinRoom", chatroom);
}
};
const renderChat = () => {
return chat.map(({ sender, message }, index) => (
<div key={index}>
<h3>
{sender}: <span>{message}</span>
</h3>
</div>
));
};
Turns out the solution is simple. Put the socket into the useEffect and create state for it.
const [socket, setSocket] = useState({});
useEffect(() => {
const socket = io(BASE_URL);
setSocket(socket);
socket.on("msgToClient", (msg) => {
setChat([...chat, { ...msg }]);
});
}, []);

Resources