

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 连接到 Amazon DCV 服务器并获取第一帧
<a name="establish-connection"></a>

以下教程说明了如何为自定义 Web 客户端准备 HTML 页面，如何进行身份验证并连接到 Amazon DCV 服务器，以及如何从 Amazon DCV 会话接收流式传输的内容的第一帧。

**Topics**
+ [步骤 1：准备 HTML 页面](#prep-html)
+ [步骤 2：验证身份、连接并获取第一帧](#auth-conn)
+ [额外任务：自动创建 HTML 登录表单](#get-token)

## 步骤 1：准备 HTML 页面
<a name="prep-html"></a>

 在您的网页中，您必须加载所需的 JavaScript 模块，并且必须添加一个有效的 `<div>` HTML 元素，该元素必须具有有效的 `id` Amazon DCV Web Client SDK，以便从远程 Amazon DCV 服务器提取内容流。

例如：

```
<!DOCTYPE html>
<html lang="en" style="height: 100%;">
  <head>
    <title>DCV first connection</title>
  </head>
  <body style="height: 100%;">
    <div id="root" style="height: 100%;"></div>
    <div id="dcv-display"></div>
    <script type="module" src="index.js"></script>
  </body>
</html>
```

## 步骤 2：验证身份、连接并获取第一帧
<a name="auth-conn"></a>

本节说明了如何完成用户身份验证过程，如何连接 Amazon DCV 服务器以及如何从 Amazon DCV 服务器接收第一帧内容。

 首先，从 `index.js` 文件中导入 Amazon DCV Web Client SDK。可以将其作为通用模块定义（UMD）模块导入，如下所示：

```
import "./dcvjs/dcv.js"
```

 否则，从版本开始`1.1.0`，也可以将其作为 ECMAScript 模块 (ESM) 从相应的包中导入，如下所示：

```
import dcv from "./dcvjs/dcv.js"
```

定义用于存储身份验证对象、连接对象和 Amazon DCV 服务器 URL 的变量。

```
let auth,
    connection,
    serverUrl;
```

 在脚本加载时记录 Amazon DCV Web Client SDK 版本，并在页面加载时调用 `main` 函数。

```
console.log("Using Amazon DCV Web Client SDK version " + dcv.version.versionStr);
document.addEventListener('DOMContentLoaded', main);
```

 `main` 函数设置日志级别，并启动身份验证过程。

```
function main () {
  console.log("Setting log level to INFO");
  dcv.setLogLevel(dcv.LogLevel.INFO);

  serverUrl = "https://your-dcv-server-url:port/";

  console.log("Starting authentication with", serverUrl);

  auth = dcv.authenticate(
    serverUrl,
    {
      promptCredentials: onPromptCredentials,
      error: onError,
      success: onSuccess
    }
  );
}
```

 `promptCredentials`、`error` 和 `success` 函数是在身份验证过程中必须定义的必需回调函数。

 如果 Amazon DCV 服务器提示输入凭证，则 `promptCredentials` 回调函数从 Amazon DCV 服务器接收请求的凭证质询。如果 Amazon DCV 服务器配置为使用系统身份验证，您必须提供登录凭证。以下代码示例假设用户名是 `my_dcv_user`，密码是 `my_password`。

 如果身份验证失败，则 `error` 回调函数从 Amazon DCV 服务器收到一个错误对象。

 如果身份验证成功，则 `success` 回调函数收到一个对象对数组，其中包括允许 `my_dcv_user` 用户在 Amazon DCV 服务器上连接到的每个会话的会话 ID（`sessionId`）和授权令牌（`authToken`）。以下代码示例调用 connect 函数，并连接到数组中返回的第一个会话。

**注意**  
在以下代码示例中，将 `MY_DCV_USER` 替换为您自己的用户名，并将 `MY_PASSWORD` 替换为您自己的密码。

```
function onPromptCredentials(auth, challenge) {
  // Let's check if in challege we have a username and password request
  if (challengeHasField(challenge, "username") && challengeHasField(challenge, "password")) {
    auth.sendCredentials({username: MY_DCV_USER, password: MY_PASSWORD})
  } else {
    // Challenge is requesting something else...
  }
}

function challengeHasField(challenge, field) {
  return challenge.requiredCredentials.some(credential => credential.name === field);
}

function onError(auth, error) {
  console.log("Error during the authentication: " + error.message);
}

// We connect to the first session returned
function onSuccess(auth, result) {
  let {sessionId, authToken} = {...result[0]};

  connect(sessionId, authToken);
}
```

 连接到 Amazon DCV 服务器。从 Amazon DCV 服务器收到第一帧时，将调用 `firstFrame` 回调方法。

```
function connect (sessionId, authToken) {
  console.log(sessionId, authToken);

  dcv.connect({
    url: serverUrl,
    sessionId: sessionId,
    authToken: authToken,
    divId: "dcv-display",
    callbacks: {
      firstFrame: () => console.log("First frame received")
    }
  }).then(function (conn) {
    console.log("Connection established!");
    connection= conn;
  }).catch(function (error) {
    console.log("Connection failed with error " + error.message);
  });
}
```

## 额外任务：自动创建 HTML 登录表单
<a name="get-token"></a>

 在调用 `promptCredentials` 回调函数时，将会返回 `challenge` 对象。它包括一个名为 `requiredCredentials` 的属性，该属性是一个对象数组 - Amazon DCV 服务器请求的每个凭证一个对象。每个对象包含请求的凭证的名称和类型。您可以使用 `challenge` 和 `requiredCredentials` 对象自动创建 HTML 登录表单。

以下代码示例说明了如何执行该操作。

```
let form,
    fieldSet;

function submitCredentials (e) {
  var credentials = {};
  fieldSet.childNodes.forEach(input => credentials[input.id] = input.value);
  auth.sendCredentials(credentials);
  e.preventDefault();
}

function createLoginForm () {
  var submitButton = document.createElement("button");

  submitButton.type = "submit";
  submitButton.textContent = "Login";

  form = document.createElement("form");
  fieldSet = document.createElement("fieldset");

  form.onsubmit = submitCredentials;
  form.appendChild(fieldSet);
  form.appendChild(submitButton);

  document.body.appendChild(form);
}

function addInput (name) {
  var type = name === "password" ? "password" : "text";

  var inputField = document.createElement("input");
  inputField.name = name;
  inputField.id = name;
  inputField.placeholder = name;
  inputField.type = type;
  fieldSet.appendChild(inputField);
}

function onPromptCredentials (_, credentialsChallenge) {
  createLoginForm();
  credentialsChallenge.requiredCredentials.forEach(challenge => addInput(challenge.name));
}
```