NODEJS,ソケットIO,MongoDBを用いた実時間チャットルームシステムの実現
“Socket . ioは、ブラウザとサーバーの間のリアルタイム、双方向、イベントベースの通信を可能にするライブラリです”.基本的にはソケット.IOは、アプリケーション間のリアルタイム通信を即座に許可します.それは他のアプリにイベントを放出するアプリを許可することによって動作し、イベントを受信するアプリケーションは、彼らが好きなように処理することができます.また、トラフィックを分離する名前空間とチャットルームを提供します.WebSocketとソケットの最善の用途の一つです.iOSは、リアルタイムのチャットアプリです.
この記事では、我々はゼロからのリアルタイムのチャットルームシステムを構築します.フロントエンド(クライアント側)については話をしません.その結果、フロントエンドのための準備された反応プロジェクトを使用し、バックエンドのために(ノード. js)を表現します.ソケット.IOサーバはバックエンドで使用されます、そして、認可はMongoDBのデータベースとマングースパッケージによって提供されます.したがって、このブログでは、チャットルームの仕組みの基礎を説明しようとしますが、CSS(Style Parts)を必要としていて、ファイルに反応してくださいGitHub レポ.
私はあなたが興奮してほしい!
これは、我々が何を構築するかのプレビューです
前もって
JavaScript、MongoDB、Expressの基本的な知識は、反応が必要です.私はNPMとノードがインストールされていると仮定し、どのように彼らは(少なくとも基本)を動作知っている.
それで始めましょう.
最初のステップは
CORSエラー:
私は、誰でもCorsエラーと戦っていると思っています.これらのエラーを解決することは、CORS構成をセットアップして、以下のコードを適用することによって、より挑戦的でありません;
私たちは3つのモデルを持っている
ユーザーの作成に飛び込みましょう.JSモデル
このモデルでは、入力フィールドをバリデータパッケージをターミナルにインストールすることで検証する必要があります.
また、私たちは
ルーティングは、クライアントの要求がアプリケーションのエンドポイントによってどのように扱われるかを定義します.ルートを実装するための2つの方法があります.フレームワークを使用して、フレームワークを使用せずに.このプロジェクトでは、Expressフレームワークを使用します.
データベースモデルを作成した後に、必要なルートを実行する必要があります
まず、サーバー側のルートにルートフォルダを作成し、このフォルダにファイルを作成し、名前を付けます
まず、ユーザを登録する必要があります.これについては、入力データを使用してデータベースに保存します(パスワードを事前に保存するフックを使用するので、ここでハッシュする必要はありません).それから、JSONWebTokenパッケージの助けを借りて、トークンを構築し、クッキーとして保存します(関数をビルドし、createJWTという名前のトークンを作成するために).最後に、ビルドしたユーザーをJSONコマンドを通じてクライアント側に返します.
明らかに、クッキーを読むには、クッキーパーサーパッケージをインストールする必要があります.jsファイル
signup関数:
マングースは楽しむが
さて、私たちは1 ms後に期限切れになる空の代替クッキーを作るべきです.その後、
クライアント側では、この関数を使用してユーザーのログをチェックします.このチェックを行うのはJWTクッキーをデコードし、データベース内のユーザーの存在を確認することで可能です.トークンのデコードは
今、インデックスに戻ります.JSはソケットで動作を開始します.IO、しかし、その前に、我々は3つの変数、すなわち部屋、メッセージとユーザーで我々のモデルを必要としなければなりません.
プロジェクトをきれいにするには、まずファイル名を作成します
Utiljsファイル
このファイルでは、各部屋のすべてのユーザーの情報がユーザー配列で保存されます.
adduser関数では、まずユーザ配列のユーザ情報の有無をチェックします.ユーザがユーザ配列に存在しない場合、
RemoveUser関数では、ログアウトしたユーザーのソケットIDを受け取り、ユーザの配列のインデックスを探します.最後に、
GetUser関数では、ソケットIDを受け取り、ユーザー配列からユーザーの情報を要求し、それを返します.
使用してソケットにアクセスできます
を返します.コードを使う
に
チャンネル登録者
心から
孫徳華
この記事では、我々はゼロからのリアルタイムのチャットルームシステムを構築します.フロントエンド(クライアント側)については話をしません.その結果、フロントエンドのための準備された反応プロジェクトを使用し、バックエンドのために(ノード. js)を表現します.ソケット.IOサーバはバックエンドで使用されます、そして、認可はMongoDBのデータベースとマングースパッケージによって提供されます.したがって、このブログでは、チャットルームの仕組みの基礎を説明しようとしますが、CSS(Style Parts)を必要としていて、ファイルに反応してくださいGitHub レポ.
私はあなたが興奮してほしい!
これは、我々が何を構築するかのプレビューです
前もって
JavaScript、MongoDB、Expressの基本的な知識は、反応が必要です.私はNPMとノードがインストールされていると仮定し、どのように彼らは(少なくとも基本)を動作知っている.
それで始めましょう.
最初のステップは
index.js
サーバー側のファイルを開き、次のコードを端末/コマンドラインウィンドウに書き込みます.npm i express socket.io mongoose cors
一旦終了すると、以下のコードを使用してモジュールを必要とし、サーバーを実行できます.const express = require('express');
const app = express();
const http = require('http').createServer(app);
const mongoose = require('mongoose');
const socketio = require('socket.io');
const io = socketio(http);
const mongoDB = "Your MongoDB Connection Address";
const PORT = process.env.PORT || 5000;
app.use(express.json()); //it help us to send our data to the client side
mongoose.connect(mongoDB,
{useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.log('connected'))
.catch(err => console.log(err))
http.listen(PORT, () => {
console.log(`listening on port ${PORT}`);
});
続ける前に、いくつかのヒントがあります.CORSエラー:
私は、誰でもCorsエラーと戦っていると思っています.これらのエラーを解決することは、CORS構成をセットアップして、以下のコードを適用することによって、より挑戦的でありません;
const cors = require('cors');
const corsOptions = {
origin: 'http://localhost:3000', // your frontend server address
credentials: true,
optionsSuccessStatus: 200
}
app.use(cors(corsOptions));
しかし、ソケットIOに接続する際にCORSエラーがあるならば、IOは以下のように構成されなければなりません;const io = socketio(http,{
cors: {
origin: "http://localhost:3000", // your frontend server address
methods: ["GET", "POST"]
}
});
MongoDBモデルの作成私たちは3つのモデルを持っている
Message.js
, Room.js
, and User.js
. それぞれのモデルには特定の設定があります.部屋JSはただの部屋の名前を保存します.JSは認証のためにユーザの名前、電子メール、およびパスワードを格納します.メッセージ.JSは、名前、ユーザー名ID、RoomRound ID、テキスト、タイムスタンプフィールドを格納します.これらのモデルの構築に違いがないので、ユーザーの作成に役立ちます.jsモデル.あなたが私の2つの他のモデルを見ることができると言及する価値がありますGitHub .ユーザーの作成に飛び込みましょう.JSモデル
このモデルでは、入力フィールドをバリデータパッケージをターミナルにインストールすることで検証する必要があります.
また、私たちは
pre-save
このモデルでフックをデータベースに格納する前にハッシュをハッシュします.Pre
スキーマレベルで定義されたミドルウェアであり、実行されるときにクエリまたはドキュメント自体を変更できます.エーPre-save
フックは、ドキュメントが保存されるときに実行されるミドルウェアです.const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const { isEmail } = require('validator');
const userSchema = new mongoose.Schema({
name: {
type: String,
required: [true, 'Please enter a name']
},
email: {
type: String,
required: [true, 'Please enter a email'],
unique: true,
lowercase: true,
validate: [isEmail, 'Please enter a valid email address']
},
password: {
type: String,
required: [true, 'Please enter a password'],
minlength: [6, 'The password should be at least 6 characters long']
},
})
userSchema.pre('save', async function (next) {
const salt = await bcrypt.genSalt();
this.password = await bcrypt.hash(this.password, salt);
next()
})
const User = mongoose.model('user', userSchema);
module.exports = User;
ルーティングの実装ルーティングは、クライアントの要求がアプリケーションのエンドポイントによってどのように扱われるかを定義します.ルートを実装するための2つの方法があります.フレームワークを使用して、フレームワークを使用せずに.このプロジェクトでは、Expressフレームワークを使用します.
データベースモデルを作成した後に、必要なルートを実行する必要があります
/signup
, /login
, /logout
, and /verifyuser
. 我々は、ログイン経路には、ログインしていないユーザーをガイドし、チャットへのアクセスを防ぐために、クライアント側の認証を調査するVerifyUserルートを使用します.まず、サーバー側のルートにルートフォルダを作成し、このフォルダにファイルを作成し、名前を付けます
authRoute.js
, 次に以下のコードを書きます:const { Router } = require('express');
const authController = require('../controllers/authControllers');
const router = Router();
router.post('/signup', authController.signup)
router.post('/login', authController.login)
router.get('/logout', authController.logout)
router.get('/verifyuser',authController.verifyuser)
module.exports = router;
その後、auperteを使用します.この短いコードをインデックスに追加する必要があります.jsファイルconst authRoutes = require('./routes/authRoutes');
app.use(authRoutes);
コントローラファイルの作成まず、ユーザを登録する必要があります.これについては、入力データを使用してデータベースに保存します(パスワードを事前に保存するフックを使用するので、ここでハッシュする必要はありません).それから、JSONWebTokenパッケージの助けを借りて、トークンを構築し、クッキーとして保存します(関数をビルドし、createJWTという名前のトークンを作成するために).最後に、ビルドしたユーザーをJSONコマンドを通じてクライアント側に返します.
明らかに、クッキーを読むには、クッキーパーサーパッケージをインストールする必要があります.jsファイル
const cookieParser = require('cookie-parser');
app.use(cookieParser());
既に知っているかもしれませんが、コードを書くためには、サーバー側のルートでコントローラという名前のフォルダを作成し、このフォルダにファイルを作り、名前をつける必要がありますauthController.js
, 次に以下のコードを書きます:const User = require('../models/User');
const jwt = require('jsonwebtoken');
const maxAge = 24 * 60 * 60 // equal one day in second
const createJWT = id => {
return jwt.sign({ id }, 'chatroom secret', {
expiresIn: maxAge
})
}
'チャットルーム秘密'我々はトークンをデコードするために使用するsignup関数:
module.exports.signup = async (req, res) => {
const { name, email, password } = req.body;
try {
const user = await User.create({ name, email, password });
const token = createJWT(user._id);
// create a cookie name as jwt and contain token and expire after 1 day
// in cookies, expiration date calculate by milisecond
res.cookie('jwt', token, { httpOnly: true, maxAge: maxAge * 1000 })
res.status(201).json({ user });
} catch (error) {
let errors = alertError(error);
res.status(400).json({ errors });
}
}
ログイン機能マングースは楽しむが
create
メソッドを使用して、signup関数でユーザを作成しますlogin
メソッドとユーザの終わりに手動で設定する必要があります.以下のコードを使用するJSモデルuserSchema.statics.login = async function (email, password){
const user = await this.findOne({email});
if(user){
const isAuthenticated = await bcrypt.compare(password,user.password);
if(isAuthenticated){
return user;
}else{
throw Error('Incorrect password');
}
}else{
throw Error('Incorrect email');
}
}
このメソッドは、ユーザーのメールとパスワードが必要です.人の情報がデータベースで利用できるならば、それはエラーを返す他の情報を返します.ユーザー情報を返す場合、CreateJWT関数を使用して、クッキーを作成します.最後に、ユーザー情報またはエラーをクライアント側に返します.module.exports.login = async (req, res) => {
const { email, password } = req.body;
try {
const user = await User.login(email, password );
const token = createJWT(user._id);
res.cookie('jwt', token, { httpOnly: true, maxAge: maxAge * 1000 })
res.status(201).json({ user });
} catch (error) {
let errors = alertError(error);
res.status(400).json({ errors });
}
}
ログアウト関数さて、私たちは1 ms後に期限切れになる空の代替クッキーを作るべきです.その後、
{logout:true}
クライアント側に送信する必要がありますmodule.exports.logout = (req, res) => {
res.cookie('jwt',"",{maxAge:1});
res.status(200).json({logout: true});
}
verifyuser関数:クライアント側では、この関数を使用してユーザーのログをチェックします.このチェックを行うのはJWTクッキーをデコードし、データベース内のユーザーの存在を確認することで可能です.トークンのデコードは
verify
JSONWebTokenパッケージのメソッド.ユーザーが既にログインしている場合は、ユーザー側の情報をクライアント側に返します.module.exports.verifyuser = (req, res, next)=>{
const token = req.cookies.jwt;
if(token){
jwt.verify(token,'chatroom secret',async (err,decodedToken)=>{
if(err){
console.log(err.message);
}else{
let user = await User.findById(decodedToken.id);
res.json(user);
next();
}
})
}else{
next();
}
}
ソケット上で作業を始めましょう.IO論理今、インデックスに戻ります.JSはソケットで動作を開始します.IO、しかし、その前に、我々は3つの変数、すなわち部屋、メッセージとユーザーで我々のモデルを必要としなければなりません.
プロジェクトをきれいにするには、まずファイル名を作成します
util.js
サーバー側のルートフォルダでaddUser
, getUser
, and removeUser
このファイルの関数.最後に、これらの関数をindex.js
ファイル.Utiljsファイル
このファイルでは、各部屋のすべてのユーザーの情報がユーザー配列で保存されます.
adduser関数では、まずユーザ配列のユーザ情報の有無をチェックします.ユーザがユーザ配列に存在しない場合、
push
この配列へのメソッド.最後に、この関数はユーザを返します.RemoveUser関数では、ログアウトしたユーザーのソケットIDを受け取り、ユーザの配列のインデックスを探します.最後に、
splice
ユーザーを配列から削除します.GetUser関数では、ソケットIDを受け取り、ユーザー配列からユーザーの情報を要求し、それを返します.
const users = [];
const addUser = ({ socket_id, name, user_id, room_id }) => {
const exist = users.find(user => user.room_id === room_id && user.user_id === user_id);
if (exist) {
return { error: 'User already exist in this room' }
}
const user = { socket_id, name, user_id, room_id };
users.push(user)
console.log('users list', users)
return { user }
}
const removeUser = (socket_id) => {
const index = users.findIndex(user => user.socket_id === socket_id);
if (index !== -1) {
return users.splice(index, 1)[0]
}
}
const getUser = (socket_id) => users.find(user => user.socket_id === socket_id)
module.exports = { addUser, removeUser, getUser }
ソケットの実装使用してソケットにアクセスできます
io.on(‘connection’,(socket)=>{ … })
また、このコードを通してソケットに変更を加えることもできます.を返します.コードを使う
socket.emit('channel name',variable or text message to send)
送信およびコードsocket.on('channel name',variable to receive)
情報と変数を必要とするために.さて、どのように我々はデータベースからクライアント側にクライアントを送信する方法を知っている必要があります.に
join channel
, クライアント側からユーザー情報を受け取り、AddUser関数を使用してユーザー配列に保存します.その後、コードを使ってsocket.join(room_id)
, 我々は、希望の部屋にユーザーを保存することができますし、他のユーザーは、その部屋のメンバーであることを条件に人のポストが表示されます.このように、私たちはソケットを整理します.チャンネル登録者
'get-message-history'
, 我々は、クライアント側からのIDを受信し、メッセージのモデルを介して部屋チャットを必要とします.そして、結果をクライアント側に返します.その結果、ログインしているユーザーは、データベースに保存される過去のメッセージを見ることができます.io.on('connection', (socket) => {
console.log(socket.id);
Room.find().then(result => {
socket.emit('output-rooms', result)
})
socket.on('create-room', name => {
const room = new Room({ name });
room.save().then(result => {
io.emit('room-created', result)
})
})
socket.on('join', ({ name, room_id, user_id }) => {
const { error, user } = addUser({
socket_id: socket.id,
name,
room_id,
user_id
})
socket.join(room_id);
if (error) {
console.log('join error', error)
} else {
console.log('join user', user)
}
})
socket.on('sendMessage', (message, room_id, callback) => {
const user = getUser(socket.id);
const msgToStore = {
name: user.name,
user_id: user.user_id,
room_id,
text: message
}
console.log('message', msgToStore)
const msg = new Message(msgToStore);
msg.save().then(result => {
io.to(room_id).emit('message', result);
callback()
})
})
socket.on('get-messages-history', room_id => {
Message.find({ room_id }).then(result => {
socket.emit('output-messages', result)
})
})
socket.on('disconnect', () => {
const user = removeUser(socket.id);
})
});
最後に、私はあなたがすべてのこの記事を気に入っていただければ幸いです、そして、あなたが質問をするならば、あなたはコメントセクションに彼らを置くことができます.できるだけ早く帰ってきます.再びあなたの時間を感謝します.あなたの将来の努力のすべてのあなたのベストを祈ります.心から
孫徳華
Reference
この問題について(NODEJS,ソケットIO,MongoDBを用いた実時間チャットルームシステムの実現), 我々は、より多くの情報をここで見つけました https://dev.to/sasandehghanian/implementation-of-real-time-chatroom-system-using-nodejs-socket-io-mongodb-4ndiテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol