通过 WebRTC 在 Web 浏览器中运行 Web 服务器
Smoke 使浏览器能够通过 WebRTC 运行微型 Web 服务器
import { Network } from '@sinclair/smoke'
// ------------------------------------------------------------------
//
// Create a Virtual Network
//
// ------------------------------------------------------------------
const { Http } = new Network ( )
// ------------------------------------------------------------------
//
// Create a Http Listener on a Virtual Port
//
// ------------------------------------------------------------------
Http . listen ( { port : 5000 } , request => new Response ( 'hello webrtc' ) )
// ------------------------------------------------------------------
//
// Fetch data over WebRTC
//
// ------------------------------------------------------------------
const text = Http . fetch ( 'http://localhost:5000' ) . then ( r => r . text ( ) )
$ npm install @sinclair/smoke
Smoke 是一个实验性浏览器网络和存储框架,可通过 WebRTC 提供 Http、Tcp 和 WebSocket 模拟,并通过 IndexedDB 提供大文件存储。它是作为在浏览器中开发对等 Web 服务的基础而构建的,每个浏览器都可以通过应用程序控制的虚拟网络进行访问。
Smoke 将 WebRTC 重塑为 WinterCG 兼容接口,使传统 Web 服务器应用程序能够在服务器和浏览器环境之间移植。它的开发是为了支持替代软件架构,其中以用户为中心的服务可以从云中移出并在浏览器中点对点运行。
许可麻省理工学院
烟雾网络 API 通过网络对象提供。网络对象表示与共享信令集线器的活动连接,并公开用于与连接到同一集线器的其他网络对象进行通信的 Http、网络和媒体功能。
import { Network , Hubs } from '@sinclair/smoke'
const { Http , Net , Media , Hub } = new Network ( { hub : new Hubs . Private ( ) } )
const address = await Hub . address ( ) // The address of this Network object.
专用集线器是内存中的中继,它通过浏览器的 BroadcastChannel API 转发 WebRTC ICE 消息。专用中心只能将消息中继到同一浏览器进程中运行的页面和其他选项卡。由于专用集线器无法促进当前页面之外的连接,因此它被视为专用。该集线器是默认的。
import { Network , Hubs } from '@sinclair/smoke'
const { Http } = new Network ( { hub : new Hubs . Private ( ) } )
该中心的实施目前正在等待中。
import { Network , Hubs } from '@sinclair/smoke'
const { Http } = new Network ( { hub : new Hubs . Public ( 'ws://server/hub' ) } )
Http API 支持通过 WebRTC 进行 Http 侦听和获取。它还提供 WebSocket 模拟。
const { Http } = new Network ( )
使用listen函数接收来自远程对等点的Http请求。
Http . listen ( { port : 5000 } , request => new Response ( 'hello' ) )
使用 fetch 函数向远程对等点发出 Http 请求。
const response = await Http . fetch ( 'http://localhost:5000' )
const message = await response . text ( )
使用升级功能将Http请求转换为WebSocket
Http . listen ( { port : 5000 } , request => Http . upgrade ( request , ( socket ) => socket . send ( 'hello' ) ) )
使用 connect 函数连接到远程 WebSocket 服务器。
const socket = await Http . connect ( 'ws://localhost:5000' )
socket . on ( 'message' , ( event ) => console . log ( event . data ) )
socket . on ( 'error' , ( event ) => console . log ( event ) )
socket . on ( 'close' , ( event ) => console . log ( event ) )
Net API 通过 RTCDataChannel 提供 Tcp 仿真
const { Net } = new Network ( )
使用listen 函数接受传入的套接字。
Net . listen ( { port : 5000 } , async socket => {
const data = await socket . read ( )
await socket . write ( data )
await socket . close ( )
} )
使用 connect 函数建立与远程侦听器的网络连接。
const socket = await Net . connect ( { hostname : 'localhost' , port : 5000 } )
await socket . write ( new Uint8Array ( 1000 ) )
const data = await socket . read ( ) // Uint8Array()
const end = await socket . read ( ) // null
Media API 提供通过 WebRTC 发送和接收 MediaStream 对象的功能。
const { Media } = new Network ( )
使用listen函数监听传入的MediaStream对象
Media . listen ( { port : 6000 } , ( receiver ) => {
const video = document . createElement ( 'video' )
video . srcObject = receiver . mediastream
video . play ( )
document . body . appendChild ( video )
receiver . on ( 'close' , ( ) => document . removeChild ( video ) )
} )
使用 send 函数将 MediaStream 发送到侦听器
const sender = await Media . send ( { hostname : 'localhost' , port : 6000 } , new MediaStream ( [ ... ] ) )
sender . close ( ) // stop sending live media
使用音频函数创建可流式传输的音频源。
const audio = Media . audio ( { src : './audio.mp3' } )
const sender = Media . send ( { hostname : 'localhost' , port : 6000 } , audio . mediastream )
使用 video 函数创建可流式传输的 VideoSource。
const video = Media . video ( { src : './video.mp4' } )
const sender = Media . send ( { hostname : 'localhost' , port : 6000 } , video . mediastream )
使用pattern函数生成MediaStream测试模式。此功能对于在没有网络摄像头或其他媒体源的情况下测试实时媒体流非常有用。
const pattern = Media . pattern ( )
const sender = Media . send ( { port : 5000 } , pattern . mediastream )
Smoke 提供了一个分层文件系统,能够在浏览器中存储大文件。该文件系统由 IndexedDB 支持,支持流式读写、目录枚举、复制、移动、重命名以及文件和目录监视事件。它被设计为充当网络服务的静态文件存储,但也可以用作需要在浏览器中存储大文件的应用程序的通用文件系统。
使用 open 函数打开具有给定数据库名称的文件系统。如果数据库不存在,则会创建该数据库。
import { FileSystem } from '@sinclair/smoke'
const Fs = await FileSystem . open ( '<database-name>' )
使用 stat 函数返回有关文件或目录的信息。
const stat = await Fs . write ( '/path/file.txt' )
使用exists函数检查路径是否存在。
const exists = await Fs . exists ( '/path/file.txt' )
使用 mkdir 函数创建目录。
await Fs . mkdir ( '/media/videos' )
使用 readdir 函数返回给定目录路径的 stat 对象。
const stats = await Fs . readdir ( '/media/videos' )
使用 blob 函数将 Blob 对象返回到文件路径。
const blob = await Fs . readdir ( '/video.mp4' )
const url = URL . createObjectUrl ( blob )
使用 write 和 writeText 函数写入文件内容。
await Fs . write ( '/path/file.dat' , new Uint8Array ( [ 1 , 2 , 3 , 4 ] ) )
await Fs . writeText ( '/path/file.txt' , 'hello world' )
使用 read 和 readText 函数将从文件中读取内容。
const buffer = await fs . read ( '/path/file.dat' )
const content = await Fs . readText ( '/path/file.txt' )
使用删除功能可以删除文件或目录。
await Fs . delete ( '/path/file.txt' )
使用重命名功能可以重命名文件或目录。
await Fs . writeText ( '/path/fileA.txt' , '...' )
await Fs . rename ( '/path/fileA.txt' , 'fileB.txt' )
使用复制功能将文件或目录复制到目标目录中。
await Fs . writeText ( '/path/fileA.txt' , '...' )
await Fs . copy ( '/path/fileA.txt' , '/backup' )
使用 move 函数将文件或目录移动到目标目录中。
await Fs . writeText ( '/path/fileA.txt' , '...' )
await Fs . move ( '/path/fileA.txt' , '/backup' )
使用 watch 函数来监视文件和目录事件。
Fs . watch ( '/dir' , event => console . log ( event ) )
Smoke 对社区贡献开放。请确保在提交拉取请求之前提交一个未解决的问题。 Smoke 项目在接受新功能之前更喜欢公开的社区讨论。