Skip to content

Namespaces

Video Lecture

Namespaces Namespaces

 (Pay Per View)

You can use PayPal to purchase a one time viewing of this video for $1.49 USD.

Pay Per View Terms

  • One viewing session of this video will cost the equivalent of $1.49 USD in your currency.
  • After successful purchase, the video will automatically start playing.
  • You can pause, replay and go fullscreen as many times as needed in one single session for up to an hour.
  • Do not refresh the browser since it will invalidate the session.
  • If you want longer-term access to all videos, consider purchasing full access through Udemy or YouTube Memberships instead.
  • This Pay Per View option does not permit downloading this video for later viewing or sharing.
  • All videos are Copyright © 2019-2025 Sean Bradley, all rights reserved.

Description

It is possible to have one socket server, and have several types of clients connect to it.

To separate command listeners for different types of applications, connecting to the one socket server, you can use namespaces.

Note that the default namespace when connecting to a Socket.IO server will be "/".

const socket = io()

Is the same as,

const socket = io('/')

If you wanted the one socket server, to deliver random numbers, and also run the collaboration painter program, then the namespaces you could set up may be rng and colabPainter.

./src/server/server.ts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import { createServer } from 'http'
import { Server } from 'socket.io'
import * as express from 'express'
import * as path from 'path'

const port = 3000

const app = express()
app.use(express.static(path.join(__dirname, '../client')))

const server = createServer(app)

const io = new Server(server)

io.of('/rng').on('connection', (socket) => {
  console.log('a user connected : ' + socket.id)

  socket.emit('message', 'Hello ' + socket.id)
})

io.of('/colabPainter').on('connection', (socket) => {
  console.log('a user connected : ' + socket.id)

  socket.on('draw', (message) => {
    socket.broadcast.emit('draw', message)
  })
})

server.listen(port, () => {
  console.log('Server listening on port ' + port)
})

setInterval(() => {
  io.of('/rng').emit('message', Math.floor(Math.random() * 100))
}, 1000)

./src/client/rng.ts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import { io } from 'socket.io-client'

const socket = io('/rng')

socket.on('connect', () => {
  document.body.innerText = 'Connected : ' + socket.id
})

socket.on('message', (message) => {
  document.body.innerHTML += '<p>' + message + '</p>'
  window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' })
})

./src/client/colabPainter.ts

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
import { io } from 'socket.io-client'

const socket = io('/colabPainter')

socket.on('draw', (message) => {
  prevX = message[0]
  prevY = message[1]
  currX = message[2]
  currY = message[3]
  color = message[4]
  draw()
})

let prevX = 0,
  currX = 0,
  prevY = 0,
  currY = 0

let color = 'black'
const thickness = 10

const canvas = document.getElementById('canvas') as HTMLCanvasElement
canvas.width = window.innerWidth
canvas.height = window.innerHeight

const ctx = canvas.getContext('2d') as CanvasRenderingContext2D

window.addEventListener('resize', function () {
  if (window.innerWidth > 0 && window.innerHeight > 0) {
    const data = ctx.getImageData(0, 0, window.innerWidth, window.innerHeight)
    canvas.width = window.innerWidth
    canvas.height = window.innerHeight
    ctx.putImageData(data, 0, 0)
  }
})

const greenButton = document.getElementById('greenButton') as HTMLDivElement
greenButton.addEventListener('click', () => {
  color = 'green'
})
const blueButton = document.getElementById('blueButton') as HTMLDivElement
blueButton.addEventListener('click', () => {
  color = 'blue'
})
const redButton = document.getElementById('redButton') as HTMLDivElement
redButton.addEventListener('click', () => {
  color = 'red'
})
const yellowButton = document.getElementById('yellowButton') as HTMLDivElement
yellowButton.addEventListener('click', () => {
  color = 'yellow'
})
const orangeButton = document.getElementById('orangeButton') as HTMLDivElement
orangeButton.addEventListener('click', () => {
  color = 'orange'
})
const blackButton = document.getElementById('blackButton') as HTMLDivElement
blackButton.addEventListener('click', () => {
  color = 'black'
})
const whiteButton = document.getElementById('whiteButton') as HTMLDivElement
whiteButton.addEventListener('click', () => {
  color = 'white'
})
const resetButton = document.getElementById('resetButton') as HTMLButtonElement
resetButton.addEventListener('click', () => {
  reset()
})

canvas.addEventListener('mousemove', (e) => {
  if (e.buttons) {
    prevX = currX
    prevY = currY
    currX = e.clientX - canvas.getBoundingClientRect().left
    currY = e.clientY - canvas.getBoundingClientRect().top
    draw()

    socket.emit('draw', [prevX, prevY, currX, currY, color])
  }
})
canvas.addEventListener('mousedown', (e) => {
  currX = e.clientX - canvas.getBoundingClientRect().left
  currY = e.clientY - canvas.getBoundingClientRect().top
})
canvas.addEventListener('mouseenter', (e) => {
  currX = e.clientX - canvas.getBoundingClientRect().left
  currY = e.clientY - canvas.getBoundingClientRect().top
})

function draw() {
  ctx.beginPath()
  ctx.moveTo(prevX, prevY)
  ctx.lineTo(currX, currY)
  ctx.strokeStyle = color
  ctx.lineWidth = thickness
  ctx.stroke()
  ctx.closePath()
}

function reset() {
  ctx.clearRect(0, 0, canvas.width, canvas.height)
}

./src/client/webpack.dev.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
const path = require('path')

module.exports = {
  mode: 'development',
  devtool: 'eval',
  devServer: {
    static: {
      directory: path.join(__dirname, '../../dist/client')
    },
    hot: true,
    proxy: [
      {
        context: ['/socket.io'],
        target: 'http://localhost:3000',
        ws: true
      }
    ]
  },
  entry: {
    rng: path.resolve(__dirname, './rng.ts'),
    colabPainter: path.resolve(__dirname, './colabPainter.ts')
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/
      }
    ]
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.js']
  },
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, '../../dist/client')
  }
}

./dist/client/rng.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>
      Socket.IO TypeScript Tutorials by Sean Bradley : https://sbcode.net/tssock/
    </title>
    <style>
      body {
        font-size: 4vw;
      }
    </style>
  </head>

  <body>
    <script type="module" src="rng.bundle.js"></script>
  </body>
</html>

./dist/client/colabPainter.html

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>
      Colab Painter : Socket.IO TypeScript Tutorials by Sean Bradley :
      https://sbcode.net/tssock/
    </title>
    <style>
      body {
        overflow: hidden;
        margin: 0px;
      }

      #canvas {
        width: 100%;
        height: 100%;
      }

      #greenButton {
        background: green;
        position: absolute;
        left: 0px;
        width: 80px;
        height: 40px;
      }

      #blueButton {
        background: blue;
        position: absolute;
        left: 80px;
        width: 80px;
        height: 40px;
      }

      #redButton {
        background: red;
        position: absolute;
        left: 160px;
        width: 80px;
        height: 40px;
      }

      #yellowButton {
        background: yellow;
        position: absolute;
        left: 240px;
        width: 80px;
        height: 40px;
      }

      #orangeButton {
        background: orange;
        position: absolute;
        left: 320px;
        width: 80px;
        height: 40px;
      }

      #blackButton {
        background: black;
        position: absolute;
        left: 400px;
        width: 80px;
        height: 40px;
      }

      #whiteButton {
        background: white;
        position: absolute;
        left: 480px;
        width: 78px;
        height: 38px;
        border: 1px solid black;
      }

      #resetButton {
        position: absolute;
        left: 560px;
        width: 78px;
        height: 40px;
        border-radius: 0;
      }
    </style>
  </head>
  <body>
    <canvas
      id="canvas"
      width="628"
      height="400"
      style="position: absolute; top: 40px; border: 5px solid"
    ></canvas>
    <div id="greenButton"></div>
    <div id="blueButton"></div>
    <div id="redButton"></div>
    <div id="yellowButton"></div>
    <div id="orangeButton"></div>
    <div id="blackButton"></div>
    <div id="whiteButton"></div>
    <input id="resetButton" type="button" value="Reset" />
    <script type="module" src="colabPainter.bundle.js"></script>
  </body>
</html>