Skip to content

Commit 6c6abf4

Browse files
committed
create updater socket
1 parent 0eb0f59 commit 6c6abf4

File tree

5 files changed

+170
-12
lines changed

5 files changed

+170
-12
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**@file useUpdaterSocket.hook.js */
2+
import { useCallback } from "react"
3+
import useWebSocket from 'react-use-websocket'
4+
import useDebouncedFunction from "./useDebouncedFunction.hook"
5+
import { useHttp } from "./http.hook"
6+
7+
const WS_PORT = process.env.WS_PORT || 3030
8+
9+
/**
10+
* Хук веб-сокета обновления данных
11+
* @param {void} updateData
12+
* @param {*} auth
13+
*/
14+
function useUpdaterSocket(updateData, auth) {
15+
const { request } = useHttp()
16+
const getSocketUrl = useCallback(async () => {
17+
return new Promise(resolve => {
18+
request("/getIp")
19+
.then((data) => {
20+
const ip = data.ip
21+
const socketAddress = "ws://" + (ip || "localhost") + ":" + WS_PORT
22+
console.log("socketAddress", socketAddress)
23+
resolve(socketAddress)
24+
})
25+
.catch((err) => console.log(err))
26+
})
27+
// eslint-disable-next-line react-hooks/exhaustive-deps
28+
}, [])
29+
const debouncedUpdate = useDebouncedFunction(updateData, 200)
30+
31+
const socketOptions = {
32+
onOpen: (e) => {
33+
sendRegisterMsg()
34+
console.log("ws open", e)
35+
},
36+
onClose: (e) => {
37+
console.log("ws close", e)
38+
},
39+
onMessage: (e) => {
40+
console.log("ws updMessage", e)
41+
debouncedUpdate()
42+
},
43+
onError: (e) => {
44+
console.error("ws error", e)
45+
},
46+
}
47+
48+
const { sendMessage } = useWebSocket(getSocketUrl, socketOptions)
49+
50+
const sendMsg = (target) => {
51+
const msg = JSON.stringify({
52+
userId: auth.userId,
53+
target
54+
})
55+
sendMessage(msg)
56+
}
57+
58+
function sendUpdateMsg() {
59+
sendMsg("update")
60+
}
61+
62+
function sendRegisterMsg() {
63+
sendMsg("register")
64+
}
65+
66+
return [sendUpdateMsg]
67+
}
68+
69+
export default useUpdaterSocket

client/src/Pages/NotesPage.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import useFetchNotes from '../Hooks/useFetchNotes.hook'
1717
import useEditNoteId from '../Hooks/useEditNoteId.hook'
1818
import useNotesArr from '../Hooks/useNotesArr.hook'
1919
import { calcOrder, fixOrders } from '../Shared/order'
20+
import useUpdaterSocket from '../Hooks/useUpdaterSocket.hook'
2021

2122
/**
2223
* Страница с заметками
@@ -52,6 +53,9 @@ function NotesPage() {
5253
/** подключение контроллера обновления данных */
5354
const [updateData] = useDataLoadingController(loadDataFromServer, setLoadedNotes, auth, 60)
5455

56+
/** подключение сокета обновления данных */
57+
const [sendUpdateMsg] = useUpdaterSocket(updateData, auth)
58+
5559
///////////
5660

5761
/**
@@ -67,7 +71,7 @@ function NotesPage() {
6771
* @param {string} target
6872
*/
6973
function loadDataToServer(note = new Note(), target = 'set') {
70-
fetchNotes(target, "POST", { note })
74+
fetchNotes(target, "POST", { note }, sendUpdateMsg)
7175
}
7276

7377
///////////

jsdoc.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"server/routes",
77
"server/models",
88
"server/middleware",
9+
"server/socket",
910
"client",
1011
"client/src",
1112
"client/src/Shared",

server/app.js

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,35 @@
55

66
const express = require('express')
77
const path = require('path')
8-
const dns = require('dns')
98
const os = require('os')
109
const mongoose = require('mongoose')
1110
const https = require('./middleware/https.middleware')
11+
const startWSS = require('./socket/wss')
1212
require('dotenv').config()
1313

14-
/**
15-
* подключение переменных среды
16-
*/
14+
//подключение переменных среды
1715
const devMode = process.env.NODE_ENV === "dev"
1816
const PORT = process.env.PORT || 5000
1917
const mongoUri = process.env.mongoUri
2018
const httpsRedirect = process.env.httpsRedirect || false
19+
const WS_PORT = process.env.WS_PORT || 3030
2120

2221
const app = express()
2322

2423
app.use(express.json({ extended: true }))
2524

25+
app.get('/getIp', (req, res) => {
26+
const ip = getIp()
27+
res.status(200).json({ ip })
28+
})
29+
2630
/**
2731
* подключение роутов
2832
*/
2933
app.use('/api/auth', require('./routes/auth.routes'))
3034
app.use('/api/notes', require('./routes/notes.routes'))
3135

36+
3237
if (httpsRedirect) app.use(https)
3338

3439
/**
@@ -52,6 +57,7 @@ if (!devMode) {
5257
async function start() {
5358
try {
5459
connectMongo(mongoUri)
60+
startWSS(WS_PORT)
5561
app.listen(PORT, logServerStart)
5662
} catch (e) {
5763
console.log('Server Error', e.message)
@@ -81,11 +87,18 @@ async function connectMongo(mongoUri) {
8187
* Вывод информации о сервере
8288
*/
8389
function logServerStart() {
84-
dns.lookup(os.hostname(), (err, address) => {
85-
const [logName, sBef, sAft] = devMode ? ['Express server', ' ', ':'] : ['React Notes App', '-', '']
86-
console.log(`\n${logName} has been started`)
87-
console.log(`${sBef} Local${sAft} http://localhost:${PORT}`)
88-
console.log(`${sBef} On Your Network${sAft} http://${address}:${PORT}`)
89-
if (err) console.log(err)
90-
})
90+
const [logName, sBef, sAft] = devMode ? ['Express server', ' ', ':'] : ['React Notes App', '-', '']
91+
console.log(`\n${logName} has been started`)
92+
console.log(`${sBef} Local${sAft} http://localhost:${PORT}`)
93+
console.log(`${sBef} On Your Network${sAft} http://${getIp()}:${PORT}`, '\n')
94+
}
95+
96+
/**
97+
* Получение ip сервера
98+
*/
99+
function getIp() {
100+
for (let key in os.networkInterfaces()) {
101+
const addr = os.networkInterfaces()[key][1].address
102+
if (addr != undefined) return addr
103+
}
91104
}

server/socket/wss.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/**@file wss.js */
2+
const WebSocket = require('ws')
3+
4+
/**
5+
* Подключение WebSocket сервера
6+
* @param {*} port
7+
*/
8+
function startWSS(port) {
9+
let wsCount = 0
10+
const wsServer = new WebSocket.Server({ port })
11+
const wsCollection = { test: [] }
12+
wsServer.on('connection', (wsClient) => {
13+
wsClient.num = ++wsCount
14+
wsClient.on("message", (data) => {
15+
try {
16+
const { userId, target } = tryParce(data)
17+
18+
if (target == "register") {
19+
wsClient.userId = userId
20+
let clients = getClients(userId)
21+
clients.push({
22+
num: wsClient.num,
23+
send: wsClient.send
24+
})
25+
wsCollection[userId] = clients
26+
27+
console.log("\ncollection \n", wsCollection, '\n')
28+
}
29+
30+
if (target == "update") {
31+
getClients(wsClient.userId).forEach((wsc) => {
32+
if ((wsClient.num === undefined) || (wsClient.num !== wsc.num)) wsc.send(data)
33+
})
34+
}
35+
36+
console.log("wsClient", wsClient.num, "messaged", target)
37+
} catch (e) {
38+
console.log("wsClient", wsClient.num, "error on messsage", e)
39+
}
40+
})
41+
wsClient.on("open", () => console.log("wsClient", wsClient.num, "opened"))
42+
wsClient.on("close", () => {
43+
wsCollection[wsClient.userId] = getClients(wsClient.userId).filter((wsc) => {
44+
return (wsClient.num === undefined) || (wsClient.num !== wsc.num)
45+
})
46+
console.log("wsClient", wsClient.num, "closed")
47+
})
48+
wsClient.on("error", () => console.log("wsClient", wsClient.num, "error"))
49+
50+
console.log("WSS connection", wsClient.num)
51+
});
52+
wsServer.on("close", () => console.log("WSS closed"))
53+
wsServer.on("error", () => console.log("WSS error"))
54+
wsServer.on("listening", () => console.log("WSS listening"))
55+
56+
/**
57+
* Получение колекции соединений по id
58+
* @param {string} userId
59+
* @returns {Array<WebSocket>}
60+
*/
61+
function getClients(userId) {
62+
return wsCollection[userId] || []
63+
}
64+
65+
function tryParce(str) {
66+
try { return JSON.parse(str) }
67+
catch (e) { return str }
68+
}
69+
}
70+
71+
module.exports = startWSS

0 commit comments

Comments
 (0)