[译]WebRTC基础实践 - 7. 配置信令服务

栏目: Html5 · 发布时间: 6年前

内容简介:在本节课程中, 我们将学习以下内容:本节的完整版代码位于要创建并保持WebRTC通话, 客户端之间需要互相交换元数据信息, 包括:

本节内容

在本节课程中, 我们将学习以下内容:

  • 通过 npm 安装 package.json 文件中指定的项目依赖
  • 运行Node.js服务器, 通过 node-static 提供静态文件服务。
  • 用Socket.IO创建消息传递服务
  • 创建聊天室以及发送聊天消息。

本节的完整版代码位于 step-04 文件夹中。

基本概念

要创建并保持WebRTC通话, 客户端之间需要互相交换元数据信息, 包括:

  • 候选网络信息(Candidate);
  • 媒介相关的邀请信息(Offer)和响应信息(answer), 比如分辨率(resolution), 编解码器(codec)等。

换句话说, 想要传输流媒体视频/数据, 必须得先互相交换元数据信息。这个过程被称为信令传输(signaling)。

在前面的小节中, 发送方和接收方都是同一个页中的 RTCPeerConnection 对象, 所以传递信令只需要在对象间直接拷贝就行, 显得特别简单, 。

在现实世界中, 发送方和接收方一般是不同的设备, 所以需要具有元数据交换的通道。

我们可以使用信令服务器( signaling server ), 来为WebRTC客户端(peers)之间传递消息。实际上这些信令消息都是纯文本格式的, 也就是将JavaScript对象序列化为字符串的形式(stringified)。

环境准备: 安装Node.js

要运行本节和接下来的示例代码(从 step-04step-06 ), 需要在本机安装 Node.js。

Node.js中文网下载链接: http://nodejs.cn/download/ ;

当然也可以直接从Node.js官网下载: https://nodejs.org/en/download/

某些平台上可以通过包管理器进行安装, 请参考: https://nodejs.org/en/download/package-manager/

安装完成后, 在项目路径下, 执行命令 npm install 安装相关的依赖, 然后可以通过命令 node index.js 来启动本地服务器。稍后会在必要时介绍这些命令。

app简介

WebRTC使用客户端方式的JavaScript API, 在实际应用中, 需要有信令服务器(消息服务)的支持, 有时还需要使用 STUN 和 TURN 服务器。 更多信息请参考: https://www.html5rocks.com/en/tutorials/webrtc/infrastructure/

在本节课程中, 我们先创建简单的 Node.js 信令服务器, 使用 Socket.IO 模块和JavaScript库来传递消息。 如果你熟悉Node.js和Socket.IO , 会比较容易理解; 如果不熟悉也没关系; 消息组件的使用非常简单。

选择正确的信令服务器

本教程使用 Socket.IO 作为信令服务器。

基于Socket.IO的设计, 将其用作消息服务简单又直接。 Socket.IO 非常适合用于学习WebRTC信令, 因为其内置了 “聊天室”(rooms) 这个概念。

当然, 对于商用级产品来说, 还有很多更好的选择。 请参考 How to Select a Signaling Protocol for Your Next WebRTC Project

在本示例中, 通过Node.js服务器启动 index.js 文件, 客户端的实现位于 index.html 文件中。

在本节中, Node.js程序做了两件事情。

一、 作为消息中继服务器:

socket.on('message', function (message) {
  log('Got message: ', message);
  socket.broadcast.emit('message', message);
});

二、 管理WebRTC视频聊天室:

if (numClients === 0) {
  socket.join(room);
  socket.emit('created', room, socket.id);
} else if (numClients === 1) {
  socket.join(room);
  socket.emit('joined', room, socket.id);
  io.sockets.in(room).emit('ready');
} else { // max two clients
  socket.emit('full', room);
}

这是个简单的WebRTC应用, 每个房间只支持两个客户端。

HTML和JavaScript代码

更新 index.html 文件, 内容如下:

<!DOCTYPE html>
<html>

<head>
  <title>Realtime communication with WebRTC</title>
  <link rel="stylesheet" href="css/main.css" />
</head>

<body>
  <h1>Realtime communication with WebRTC</h1>
  <script src="/socket.io/socket.io.js"></script>
  <script src="js/main.js"></script>
</body>
</html>

页面上没有太多东西: 所有的日志信息都在浏览器控制台输出。(要打开Chrome控制台, 可以使用快捷键 Ctrl-Shift-J , 或 F12 , Mac系统则是 Command-Option-J )。

替换 js/main.js 文件的内容:

'use strict';

var isInitiator;

window.room = prompt("Enter room name:");

var socket = io.connect();

if (room !== "") {
  console.log('Message from client: Asking to join room ' + room);
  socket.emit('create or join', room);
}

socket.on('created', function(room, clientId) {
  isInitiator = true;
});

socket.on('full', function(room) {
  console.log('Message from client: Room ' + room + ' is full :^(');
});

socket.on('ipaddr', function(ipaddr) {
  console.log('Message from client: Server IP address is ' + ipaddr);
});

socket.on('joined', function(room, clientId) {
  isInitiator = false;
});

socket.on('log', function(array) {
  console.log.apply(console, array);
});

设置 Socket.IO

在HTML文件中, 可以看到, 我们使用了一个 Socket.IO 的文件:

<script src="/socket.io/socket.io.js"></script>

work 目录中创建文件: package.json , 其内容如下:

{
  "name": "webrtc-codelab",
  "version": "0.0.1",
  "description": "WebRTC codelab",
  "dependencies": {
    "node-static": "^0.7.10",
    "socket.io": "^1.2.0"
  }
}

这就是一个应用清单文件, 主要是告知Node包管理器( npm , Node Package Manager)需要安装的依赖项。

要安装依赖, (比如我们使用的 /socket.io/socket.io.js ), 可以在 work 目录下执行命令:

npm install

如果是在国内, 可以使用 cnpm,

首先需要全局安装 cnpm:

npm install -g cnpm

然后才能使用cnpm, cnpm用法和npm完全一致:

cnpm install

然后可以看到相关的日志信息.

省略。。。

可以看到, npm 安装了 package.json 中定义的依赖项。

work 目录下创建一个新的文件 index.js , 内容如下:

注意服务端脚本不放到 js 目录中

'use strict';

var os = require('os');
var nodeStatic = require('node-static');
var http = require('http');
var socketIO = require('socket.io');

var fileServer = new(nodeStatic.Server)();
var app = http.createServer(function(req, res) {
  fileServer.serve(req, res);
}).listen(8080);

var io = socketIO.listen(app);
io.sockets.on('connection', function(socket) {

  // convenience function to log server messages on the client
  function log() {
    var array = ['Message from server:'];
    array.push.apply(array, arguments);
    socket.emit('log', array);
  }

  socket.on('message', function(message) {
    log('Client said: ', message);
    // for a real app, would be room-only (not broadcast)
    socket.broadcast.emit('message', message);
  });

  socket.on('create or join', function(room) {
    log('Received request to create or join room ' + room);

    var clientsInRoom = io.sockets.adapter.rooms[room];
    var numClients = clientsInRoom ? Object.keys(clientsInRoom.sockets).length : 0;

    log('Room ' + room + ' now has ' + numClients + ' client(s)');

    if (numClients === 0) {
      socket.join(room);
      log('Client ID ' + socket.id + ' created room ' + room);
      socket.emit('created', room, socket.id);

    } else if (numClients === 1) {
      log('Client ID ' + socket.id + ' joined room ' + room);
      io.sockets.in(room).emit('join', room);
      socket.join(room);
      socket.emit('joined', room, socket.id);
      io.sockets.in(room).emit('ready');
    } else { // max two clients
      socket.emit('full', room);
    }
  });

  socket.on('ipaddr', function() {
    var ifaces = os.networkInterfaces();
    for (var dev in ifaces) {
      ifaces[dev].forEach(function(details) {
        if (details.family === 'IPv4' && details.address !== '127.0.0.1') {
          socket.emit('ipaddr', details.address);
        }
      });
    }
  });

});

打开命令行终端, 在 work 目录下执行命令:

node index.js

也可以将这个命令保存为启动脚本, 如 startup_index.cmd 之类的脚本文件。 创建一个文本文件,输入内容,然后另存为/重命名即可。

打开浏览器, 输入地址: http://localhost:8080

打开页面时, 会提示输入房间号。如果要加入同一个房间, 则两个客户端输入相同的房间号即可, 如 “cnc”。

打开一个新标签页, 输入地址: http://localhost:8080 。 输入同样的房间号 cnc

再打开第三个标签页, 输入地址: http://localhost:8080 。 也输入同样的房间号 cnc

然后查看每个选项卡对应的控制台日志信息, 应该可以看到JavaScript中打印的日志信息。

练习与实践

  1. 可以选择哪些消息传递机制? 如果使用纯粹的 WebSocket, 会遇到哪些问题?
  2. 扩展这个应用, 会涉及哪些问题? 你能用某种技术来模拟成千上万个并发请求吗?
  3. 在这个应用中, 使用了一个JavaScript prompt 来让用户输入房间号。 试着修改程序, 将房间号放到URL之中。例如 http://localhost:8080/cnc , 则对应房间号为 cnc

知识点回顾

在本节课程中, 我们学习了:

  • 通过 npm 安装 package.json 文件中指定的项目依赖
  • 运行Node.js服务器, 通过 node-static 提供静态文件服务。
  • 用Socket.IO创建消息传递服务
  • 创建聊天室以及发送聊天消息。

本节的完整版代码位于 step-04 文件夹中。

了解更多

后续内容

接下来, 我们将学习如何通过信令服务, 让两个客户端建立对等连接。

原文链接: https://codelabs.developers.google.com/codelabs/webrtc-web/#6

翻译人员: 铁锚 - https://blog.csdn.net/renfufei

翻译日期: 2018年08月27日


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

用户故事与敏捷方法

用户故事与敏捷方法

Mike Cohn / 石永超、张博超 / 清华大学出版社 / 2010-4 / 39.00元

《用户故事与敏捷方法》详细介绍了用户故事与敏捷开发方法的结合,诠释了用户故事的重要价值,用户故事的实践过程,良好用户故事编写准则,如何搜集和整理用户故事,如何排列用户故事的优先级,进而澄清真正适合用户需求的、有价值的功能需求。 《用户故事与敏捷方法》对于软件开发人员、测试人员、需求分析师和管理者,具有实际的指导意义和重要的参考价值。一起来看看 《用户故事与敏捷方法》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

随机密码生成器
随机密码生成器

多种字符组合密码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具