Skip to content

Instantly share code, notes, and snippets.

@crosstyan
Last active June 25, 2020 17:52
Show Gist options
  • Save crosstyan/8036093d1dbdc1106352a435e95466a3 to your computer and use it in GitHub Desktop.
Save crosstyan/8036093d1dbdc1106352a435e95466a3 to your computer and use it in GitHub Desktop.
A websocket based multiroom chat with node.js.
import WebSocket from 'ws'
import mongodb, { ObjectID } from 'mongodb'
import * as querystring from 'querystring'
import {v4 as uuid} from 'uuid'
//Connect to ws://127.0.0.1:8081/thread?name=yourGroupname
//to test the server
interface WsSessionGroup{
id?: ObjectID
name?:string
wsSessions: WebSocket[]
//Or use a map with uuid
//wsSessions:Record<string,WebSocket>
}
class WsHub{
wsSessionGroupMap: Record<string, WsSessionGroup> = {}
//wsSessionGroupMap:Map<string,WsSessionGroup> = new Map
addSession(groupName:string,session:WebSocket) {
if (this.wsSessionGroupMap[groupName]==undefined){
const sessionGroup = new ThreadSessionGroup
sessionGroup.name = groupName
sessionGroup.wsSessions.push(session)
this.wsSessionGroupMap[groupName] = sessionGroup
//If you wanna use uuid map
// const uid = uuid()
// this.wsSessionGroupMap[groupName].wsSessions[uid]=session
console.log(`New group "${groupName}" created`)
}
else {
this.wsSessionGroupMap[groupName].wsSessions.push(session)
console.log(`Old group "${groupName}" connected`)
}
}
deleteSession(groupName:string,session:WebSocket) {
const sessionList = this.wsSessionGroupMap[groupName].wsSessions
sessionList.splice(sessionList.indexOf(session), 1)
console.log(`A member from group "${groupName}" disconnected`)
if (sessionList.length == 0) {
delete this.wsSessionGroupMap[groupName]
console.log(`Delete empty group "${groupName}"`)
}
}
broadcastGroup(groupName:string, message: WebSocket.Data):void {
const targetGroup = this.wsSessionGroupMap[groupName]
targetGroup?.wsSessions.forEach((session) => {
if (session.readyState === WebSocket.OPEN) {
session.send(message)
}
})
console.log(`"${message}" from "${groupName}"`)
}
}
class ThreadSessionGroup implements WsSessionGroup{
id?: ObjectID
name?:string
wsSessions: WebSocket[] =[]
}
const threadHub = new WsHub
const threadWs = new WebSocket.Server({
port: 8081,
path: "/thread",
})
threadWs.on('connection', (socket, req) => {
const reParam=req.url?.match(/(?<=\?).+/)
const urlParam = querystring.decode(reParam![0])
const sessionNameInURL = urlParam.name?.toString()!
if ('name' in urlParam) {
threadHub.addSession(sessionNameInURL,socket)
}
else {
socket.close(4001,"Params aren't correct. ")
}
socket.on('message', (message) => {
threadHub.broadcastGroup(sessionNameInURL,message)
})
socket.on('close', () => {
threadHub.deleteSession(sessionNameInURL, socket)
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment