5

Creating A WebTransport NPM Package - ShakePort

 1 year ago
source link: https://jyroneparker.com/2023/02/23/creating-a-webtransport-npm-package-shakeport/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
webtransport.png

People Are SLEEPING on WebTransport!

Of all my favorite HTML APIs the WebTransport API is definitely TOP 3. MDN explains the WebTransport API as such:

The WebTransport interface of the WebTransport API provides functionality to enable a user agent to connect to an HTTP/3 server, initiate reliable and unreliable transport in either or both directions, and close the connection once it is no longer needed.

https://developer.mozilla.org/en-US/docs/Web/API/WebTransport

It allows a web page to connect to a bidirectional HTTP/3 server to send and receive UDP datagrams either reliably or unreliably. Seriously why is no one talking about this?! In this article/tutorial, I will go through the process of creating an NPM package called ShakePort

Real-life image of me raging on the lack of WebTransport talk!

What Is HTTP/3

HTTP/3 is the third major version of the Hypertext Transfer Protocol used to exchange information on the World Wide Web, complementing the widely-deployed HTTP/1.1 and HTTP/2. Unlike previous versions which relied on the well-established TCP (published in 1974),[1] HTTP/3 uses QUIC, a multiplexed transport protocol built on UDP.[2] On 6 June 2022, IETF published HTTP/3 as a Proposed Standard in RFC9114.[3]

https://en.wikipedia.org/wiki/HTTP/3

HTTP/3 is 3x faster than HTTP/1.1 and has much less latency than its predecessors. Built using QUIC for data transfer using UDP instead of TCP. What this means for real-time sensitive applications is faster data faster execution.

Dissecting The WebTransport Class

Constructor

The constructor for the WebTransport takes in a url and an options parameter. The URL points to an instance of a HTTP/3 server to connect to. The options parameter is an optional variable that passes in a JSON object

url

A string representing the URL of the HTTP/3 server to connect to. The scheme needs to be HTTPS, and the port number needs to be explicitly specified.options Optional

An object containing the following properties:serverCertificateHashes Optional

An array of WebTransportHash objects. If specified, it allows the website to connect to a server by authenticating the certificate against the expected certificate hash instead of using the Web public key infrastructure (PKI). This feature allows Web developers to connect to WebTransport servers that would normally find obtaining a publicly trusted certificate challenging, such as hosts that are not publicly routable, or ephemeral hosts like virtual machines.

WebTransportHash objects contain two properties:algorithm

A string representing the algorithm to use to verify the hash. Any hash using an unknown algorithm will be ignored.value

BufferSource representing the hash value.

We instantiate a new instance of WebTransport with the following command

new WebTransport(url, options) 

Instance Properties

The closed read-only property of the WebTransport interface returns a promise that resolves when the transport is closed.

The datagrams read-only property of the WebTransport interface returns a WebTransportDatagramDuplexStream instance that can be used to send and receive datagrams — unreliable data transmission.

“Unreliable” means that transmission of data is not guaranteed, nor is arrival in a specific order. This is fine in some situations and provides very fast delivery. For example, you might want to transmit regular game state updates where each message supersedes the last one that arrives, and order is not important.

The incomingBidirectionalStreams read-only property of the WebTransport interface represents one or more bidirectional streams opened by the server. Returns a ReadableStream of WebTransportBidirectionalStream objects. Each one can be used to reliably read data from the server and write data back to it.

The incomingUnidirectionalStreams read-only property of the WebTransport interface represents one or more unidirectional streams opened by the server. Returns a ReadableStream of WebTransportReceiveStream objects. Each one can be used to reliably read data from the server.

The ready read-only property of the WebTransport interface returns a promise that resolves when the transport is ready to use.

Instance Methods

The close() method of the WebTransport interface closes an ongoing WebTransport session.

The createBidirectionalStream() method of the WebTransport interface opens a bidirectional stream; it returns a WebTransportBidirectionalStream object containing readable and writable properties, which can be used to reliably read from and write to the server.

The createUnidirectionalStream() method of the WebTransport interface opens a unidirectional stream; it returns a WritableStream object that can be used to reliably write data to the server.

Use Cases For WebTransport

Web Gaming

WebTransport allows not only for better performance web games in multiplayer, but it also allows for CROSS-SYSTEM PLAY! Since WebTransport is an HTTP/3 web standard you can implement it on the web, PlayStation, Xbox, and whatever else may come in the future! You may be wondering why use WebTransport instead of WebRTC. For 1 v 1 multiplayer games WebRTC will do just fine, but what if you want to build a Battle Royale style battle game that’s 50 v 50? If you are using WebRTC you will run into latency issues because WebRTC is peer-to-peer whereas WebTransport is client-server. Using UDP packets so order does not matter which is what you want for gaming.

Free hand holding gaming console
WebTransport is a major win for gaming in the web.

With WebTransport communicating with IOT devices via the web just got a whole lot easier. You can manage a fleet of hardware devices, get analytical data and issue commands in real-time. I am currently using a WebTransport server on my Raspberry Pi 4 and a Vue frontend to remotely control my Pi!

Machine Learning

Machine learning requires large datasets. By utilizing WebTransport you can send user data to your server in real-time to get better insights on your machine learning models. Take for example you are building a recommendation engine. As the user browses the site, you are sending data in real time based on what they are looking at, etc. The faster you can collect and analyze data, the more profitable your company can become.

Pub/Sub

Using the WebTransport API you can implement a pub/sub system. The simplest use case would be a notification engine (think game HUD updates in multiplayer). You can also do things like implement real-time tickers instead of relying on long-polling techniques.

Why I Created ShakePort

I created ShakePort as a basis for my real-time apps and more importantly, I’m building a game and need multiplayer networking. I decided at the beginning of the year I would post on average 1 open source package a month. So far I’m at 4! My philosophy is if you find yourself doing certain code over and over, just package that sh!t up and release it to the world. Chances are there are other developers who you are helping OR you could find devs to help make your package even better! The ShakePort suite is made up of a client (ShakePort Client) and a server (ShakePort Server) this tutorial will focus on the ShakePort Client, I will post the ShakePort Server tutorial later in the year once I finish.

The Code

This package is actually very simple, it only consists of two files:

  • A WebWorker file
  • The ShakePortClient class

Almost all of the heavy work is offloaded to the WebWorker to optimize speed and performance and utilizes window.postMessage() to send data to the main application. This way the developer has custom control on how to deal with the datagrams.

Scaffolding

Create a new directory and run the npm init command to create a new NPM package
mkdir shakeport-client

cd shakeport-client && npm init

The WebWorker

Create a worker.js file in the root of the project and input the following:

let transport, stream = null
onmessage = (e) => {
  try {
    switch(e.data.event) {
      case 'start':
        transport = initTransport(e.data.url, e.data.options)
        postMessage({event:'start', transport:transport})
      break;

      case 'setup-bidirectional':
      stream = setUpBidirectional()
      readData(stream.readable)
      break;

      case 'write-bidirectional':
      writeData(stream.writable, e.data.data)
      break;

      case 'data':

      break;

      case 'stop':
        closeTransport(e.transport)
      break;
    }
  } catch {

    postMessage({event: 'error'});
  }
}
async function initTransport(url, options = {}) {
  // Initialize transport connection
  const transport = new WebTransport(url, options);

  // The connection can be used once ready fulfills
  await transport.ready;

  return transport
}

async function readData(readable) {
  const reader = readable.getReader();
  while (true) {
    const {value, done} = await reader.read();
    if (done) {
      break;
    }
    // value is a Uint8Array.
    postMessage({event: 'data-read', data:value});
  }
}

async function writeData(writable, data) {
  const writer = writable.getWriter();
  writer.write(data)
  postMessage({event: 'data-written', data: data})
}

async function setUpBidirectional() {
  const stream = await transport.createBidirectionalStream();
  // stream is a WebTransportBidirectionalStream
  // stream.readable is a ReadableStream
  // stream.writable is a WritableStream
  return stream
}

async function setUpUnidirectional() {
  const stream = await transport.createUnidirectionalStream();
  // stream is a WebTransportBidirectionalStream
  // stream.readable is a ReadableStream
  // stream.writable is a WritableStream
  return stream
}

async function closeTransport(transport) {
    // Respond to connection closing
  try {
    await transport.closed;
    console.log(`The HTTP/3 connection to ${url} closed gracefully.`);
  } catch(error) {
    console.error(`The HTTP/3 connection to ${url} closed due to ${error}.`);
  }
}

The ShakePortClient Class

Create a class file called ShakePortClient.js in the root directory and fill it in:


export default class ShakePortClient {
  transport = null
  constructor() {
    const worker = require('./worker.js')
    console.log(worker)
    this.worker = new Worker(worker)
  }

  startClient(data = {url, options: {}}) {
    this.worker.postMessage({event:'start', ...data})
    this.worker.onmessage = (event) => {
      switch(event.data.event) {
        case 'start':
          console.log('Started')
          this.transport = event.data.transport
        break;
        case 'stop':
          this.transport = null
        break;
        case 'error':
          console.log(event.data.error)
        break;
        default:
          window.postMessage(event.data)
        break;
      }
    }
  }

  stopClient () {
    this.worker.postMessage({event:'stop'})
  }


  setUpBidirectional () {
    this.worker.postMessage({event:'setup-bidirectional'})
  }

  setUpUnidirectional () {
    this.worker.postMessage({event:'setup-unidirectional'})
  }

  writeBidirectional (data) {
    this.worker.postMessage({event:'write-bidirectional', data: data})
  }

  writeData (data) {
    this.worker.postMessage({event:'write-data', data: data})
  }

  writeUndirectional (data) {
    this.worker.postMessage({event:'write-unidirectional', data: data})
  }
  
}

Using The Package

npm install @mastashake08/shakeport-client
Then import and use

Import In Your Project

import ShakePortClient from '@mastashake08/shakeport-client'
const spc = new ShakePortClient();
spc.startClient({
  url:'<webtransport_server_url>'
})

Responding To Messages

window.addEventListener("message", (event) => {
  // Do we trust the sender of this message?  (might be
  // different from what we originally opened, for example).
  if (event.origin !== "http://example.com")
    return;

  // event.source is popup
  // event.data is "hi there yourself!  the secret response is: rheeeeet!"
}, false);

Follow Me On Social Media

e0c48dc4005b3a0b83a3ed4123bce29e?s=48&d=mm&r=g

Hackin’ on yo mainframe

mastashake08

Jyrone Parker is an American software engineer and entrepreneur from Louisville, KY. He is the owner and CEO of J Computer Solutions LLC, a full-scale IT agency that deals with hardware, networking, and software development. He is also a tech rapper and producer that goes by the name Mastashake.

Become A Sponsor

Open-source work is free to use but it is not free to develop. If you enjoy my content and would like to see more please consider becoming a sponsor on Github or Patreon! Not only do you support me but you are funding tech programs for at risk youth in Louisville, Kentucky.

Digital-Patreon-Wordmark_WhiteOnBlack-Lg.jpg?resize=247%2C173&ssl=1

Join The Newsletter

By joining the newsletter, you get first access to all of my blogs, events, and other brand-related content delivered directly to your inbox. It’s 100% free and you can opt out at any time!

Name(required)

Email(required)

By submitting your information, you're giving us permission to email you. You may unsubscribe at any time.

Like this:

Loading...

Recommend

  • 4
    • Github github.com 4 years ago
    • Cache

    spiderable-middleware NPM package

    Spiderable middleware Google, Facebook, Twitter, Yahoo, and Bing and all other crawlers and search engines are constantly trying to view your website. If your website is built on top of the JavaScript framework...

  • 10

    Will WebTransport Replace WebRTC in Near Future?Introducing WebTransport, the successor for WebRTC for real-time web communication

  • 3
    • blog.p2hp.com 2 years ago
    • Cache

    WebTransport 与 WebCodecs 初探

    什么是WebTransport? WebTransport 是WebRTC体系下的一套浏览器API,提供低延迟,client和server之间双向通信的能力。 核心的能力点包括: WebTransport 提供基于QUIC 和 HTTP3实现的API, 自动获得QUIC和HTTP3本身的特性,比如应用层的拥塞,避...

  • 5

    Best practices for creating a modern npm packageBrian ClarkSeptember 12, 2022Technology is always changing and your processes and practices need to keep up with those changes. So while npm is 12 years old, your pract...

  • 0
    • nodeweekly.com 1 year ago
    • Cache

    Creating an npm package in 2022

    Node Weekly Issue 454 « Prev

  • 0

    Experimental WebTransport over HTTP/3 support in Kestrel Chris R...

  • 6
    • blog.p2hp.com 1 year ago
    • Cache

    尝试使用 WebTransport

    WebTransport 是一种新的 API,提供低延迟、双向、客户端-服务器消息传递。了解有关其用例的更多信息,以及如何就实施的未来提供反馈。 小心 此提案在初始试用期内会继续更改。浏览器实现与本文中的信息可能存在差异。 有...

  • 3

    Web Transport 简介 WebTransport 是一个新的 Web API,使用 HTTP/3 协议来支持双向传输。它用于 Web 客户端和 HTTP/3 服务器之间的双向通信。它支持通过 不可靠的 Datagrams API 发送数据,也支持可靠的 Stream API 发送数据。

  • 5

    WebTransport 开播的应用实践之路 作者:付宇豪 2023-06-12 17:24:40 网络 WebTransport可以发挥页面多线程的优势,使用WebRTC协议,大...

  • 46

    Explore the pivotal roles of WebSockets, Server-Sent Events, Long-Polling, WebRTC, and WebTransport in shaping real-time web apps. Dive into their unique advantages, limitations, and optimal use cases for informed development choices.

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK