Skip to content
Real-time client/server communication over UDP using WebRTC and Node.js http://geckos.io
TypeScript JavaScript HTML
Branch: master
Clone or download

Latest commit

Latest commit b8efa40 May 31, 2020

Files

Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.github Added more testing files May 30, 2020
bundles v1.4.3 May 30, 2020
packages Comment out unused function May 30, 2020
readme Added ads section Apr 16, 2020
test Test forwarded messages May 30, 2020
.gitignore Use package lock for CI May 29, 2020
.prettierrc . Apr 24, 2019
CHANGELOG.md Some lerna improvements May 11, 2019
LICENSE . Apr 24, 2019
README.md Changed disconnect event to disconnect reason May 30, 2020
cheatsheet.md Moved the cheatsheet into README.md May 27, 2020
jest-puppeteer.config.js Improved Jenkins configuration May 7, 2019
jest.config.js Improved automated testing May 30, 2020
lerna.json v1.4.3 May 30, 2020
package-lock.json Use package lock for CI May 29, 2020
package.json Added more testing files May 30, 2020

README.md

logo

geckos.io

Geckos.io offers real-time client/server communication over UDP using WebRTC and Node.js

Geckos.io fits perfectly with your next HTML5 real-time multiplayer games or chat app.

NPM version Github Workflow Dependency Status Downloads Node version Minified bundle Codecov


What is it made for?

It's designed specifically for your HTML5 real-time multiplayer games by lowering the average latency and preventing huge latency spikes.

Getting Started

First things first, install it via npm:

npm install @geckos.io/client @geckos.io/server

Usage

client.js

import geckos from '@geckos.io/client'

// or add a minified version to your index.html file
// https://github.com/geckosio/geckos.io/tree/master/bundles

const channel = geckos({ port: 3000 }) // default port is 9208

channel.onConnect(error => {
  if (error) {
    console.error(error.message)
    return
  }

  channel.on('chat message', data => {
    console.log(`You got the message ${data}`)
  })

  channel.emit('chat message', 'a short message sent to the server')
})

server.js

const geckos = require('@geckos.io/server').default
// or with es6
import geckos from '@geckos.io/server'

const io = geckos()

io.listen(3000) // default port is 9208

io.onConnection(channel => {
  channel.onDisconnect(() => {
    console.log(`${channel.id} got disconnected`)
  })

  channel.on('chat message', data => {
    console.log(`got ${data} from "chat message"`)
    // emit the "chat message" data to all channels in the same room
    io.room(channel.roomId).emit('chat message', data)
  })
})

Cheatsheet

Here a list of available methods.

Client

// import geckos.io client
import geckos from '@geckos.io/client'

/**
 * start geckos client with these options
 * @param options.url default is `${location.protocol}//${location.hostname}`
 * @param options.port default is 9208
 * @param options.label Default: 'geckos.io'.
 * @param options.iceServers Default: [].
 * @param options.iceTransportPolicy Default: 'all'.
 */
const channel = geckos(options)

// once the channel is connected to the server
channel.onConnect(error => {
  if (error) console.error(error.message)

  // listens for a disconnection
  channel.onDisconnect(() => {})

  // listens for a custom event from the server
  channel.on('chat message', data => {})

  // emits a message to the server
  channel.emit('chat message', 'Hi!')

  // closes the WebRTC connection
  channel.close()
})

Server

// import geckos.io server
import geckos from '@geckos.io/server'

/**
 * start geckos server with these options
 * @param options.iceServers Default: [].
 * @param options.iceTransportPolicy Default: 'all'.
 * @param options.label Default: 'geckos.io'.
 * @param options.ordered Default: false.
 * @param options.maxPacketLifeTime Default: null.
 * @param options.maxRetransmits Default: 0.
 * @param options.cors
 * @param options.cors.origin String | (req) => string. Default '*'
 */
io = geckos(options)

/**
 * make the server listen on a port
 * @param {number} port default port is 9208
 */
io.listen()

// whenever a new channel is connected
io.onConnection(channel => {
  // the channel includes its id
  const { id } = channel

  // whenever the channel got disconnected
  // the reason will be 'disconnected', 'failed' or 'closed'
  channel.onDisconnect(reason => {})

  // listen for a custom event
  channel.on('chat message', data => {})

  // channel joins a room
  channel.join('someRoomId')

  // channel leaves a room
  channel.leave()

  // channel closes the webRTC connection
  channel.close()

  // will trigger a specific event on all channels in a
  // specific room and add the senderId as a second parameter
  channel.forward(channel.roomId).emit('chat message', 'Hello!')

  // listen for a forwarded message
  channel.on('chat message', (data, senderId) => {
    // we know that the message was forwarded if senderId is defined
    if (senderId) {
      // ...
    } else {
      // ...
    }
  })

  // emits a message to the channel
  channel.emit('chat message', 'Hello to myself!')

  // emits a message to all channels, in the same room
  channel.room.emit('chat message', 'Hello everyone!')

  // emits a message to all channels, in the same room, except sender
  channel.broadcast.emit('chat message', 'Hello friends!')

  // emits a message to all channels
  io.emit('chat message', 'Hello everyone!')

  // emits a message to all channels in a specific room
  io.room(roomId).emit('chat message', 'Hello everyone!')
})

Note: The following event names are reserved:

  • sendOverDataChannel
  • receiveFromDataChannel
  • disconnected
  • disconnect
  • connection
  • connect
  • error
  • dataChannelIsOpen
  • sendToRoom
  • sendToAll
  • forwardMessage
  • broadcastMessage
  • rawMessage

Raw Messages

You can send and receive USVString, ArrayBuffer and ArrayBufferView using rawMessages.

// emit a raw message
channel.raw.emit(rawMessage)

// emit a raw message to all users in the same room
channel.raw.room.emit(rawMessage)

// broadcast a raw message
channel.raw.broadcast.emit(rawMessage)

// listen for a raw message
channel.onRaw(rawMessage => {})

Reliable Messages

All emit function can send reliable message if needed. This is NOT meant to be used as the default. Just use it to send important messages back and forth.

It works by simply transferring multiple messages after each other. The receiver will simply reject a message if it has already been processed.

channel.emit(
  'end of game',
  {
    points: 147,
    time: 650,
    achievements: ['crucial_hit', 'golden_trophy']
  },
  {
    // Set the reliable option
    // Default: false
    reliable: true,
    // The interval between each message in ms (optional)
    // Default: 150
    interval: 150,
    // How many times the message should be sent (optional)
    // Default: 10
    runs: 10
  }
)

Servers

Standalone

import geckos from '@geckos.io/server'
const io = geckos()

io.onConnection( channel => { ... })
io.listen(3000) // default port is 9208

Node.js HTTP Server

const geckos = require('@geckos.io/server').default
const http = require('http')
const server = http.createServer()
const io = geckos()

io.addServer(server)
io.onConnection( channel => { ... })
// make sure the client uses the same port
// @geckos.io/client uses the port 9208 by default
server.listen(3000)

Express

const geckos = require('@geckos.io/server').default
const http = require('http')
const express = require('express')
const app = express()
const server = http.createServer(app)
const io = geckos()

io.addServer(server)
io.onConnection( channel => { ... })
// make sure the client uses the same port
// @geckos.io/client uses the port 9208 by default
server.listen(3000)

Deployment

You have to make sure you deploy it to a server which forwards all traffic on ports 9208/tcp (or another port you define) and 0-65535/upd to your application.

Port 9208/tcp (or another port you define) is used for the peer signaling. The peer connection itself will be on a random port between 0-65535/upd.

ICE Servers

Geckos.io provides a default list of ICE servers for testing. In production, you should probably use your own STUN and TURN servers.

const geckos = require('@geckos.io/server').default
const { iceServers } = require('@geckos.io/server')
// or
import geckos, { iceServers } from '@geckos.io/server'

// use an empty array if you are developing locally
// use the default iceServers if you are testing it on your server
const io = geckos({ iceServers: null, TESTING_LOCALLY ? [] : iceServers })

Watch a useful video about ICE Servers on YouTube.

TypeScript

Geckos.io is written in TypeScript. If you import geckos.io with the import statement, the types will be imported as well.

// client.js
import geckos, { Data } from '@geckos.io/client'

const channel = geckos({ url: 'YOUR_SERVER_URL' })

channel.onConnect(() => {
  channel.on('chat message', (data: Data) => {
    // ...
  })
})

// server.js
import geckos, { Data, Channel } from '@geckos.io/server'

const io = geckos()

io.onConnection((channel: Channel) => {
  channel.on('chat message', (data: Data) => {
    // ...
  })
})

3D HTML5 Multiplayer Games

enable3d logo

Want to make a 3D HTML5 Multiplayer Game? Take a look at one of my other projects called enable3d.

Examples

socket.io vs geckos.io vs peerjs

TODO: Note some differences here.

When to use socket.io, geckos.io or peerjs?

socket.io geckos.io peerjs
Real-Time Multiplayer Game
(with authoritative server)
Real-Time Multiplayer Game
(without authoritative server)
Turn based Multiplayer Game
(with authoritative server)
Turn based Multiplayer Game
(without authoritative server)
Chat App
Any other App with Real-Time communication

Who is using geckos.io

  • DatTank.io - is a free multiplayer browser online tank game.

New Technologies

For now WebRTC in the best way to send fast (unordered and unreliable) messages between browser and server. But once a better technology will be widely available (for example quic), we will implement it as well.

Development

To help developing geckos.io, install this repository via npm install. Test it with npm test. Then start the development server with npm run dev.

License

The BSD 3-Clause License (BSD-3-Clause) 2019 - Yannick Deubel. Please have a look at the LICENSE for more details.

You can’t perform that action at this time.