> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/creator/content-creator-zh/chang-jing-sdk7/wang-luo/network-connections.md).

# 网络连接

如何让你的场景与外部服务器和 API 通信。

你的场景可以利用暴露 API 的外部服务，你可以用它来获取最新的价格数据、天气数据或任何由 API 提供的其他信息。

你也可以搭建自己的外部服务器来辅助你的场景，并用于在玩家之间同步数据。这可以通过提供 REST API 的服务器来实现，也可以通过使用 WebSockets 的服务器来实现。

## 调用 REST API

你的场景代码可以向 REST API 发送调用以获取数据。

由于服务器可能需要一些时间来发送响应，你必须将此命令作为 [异步函数](/creator/content-creator-zh/chang-jing-sdk7/bian-cheng-mo-shi/async-functions.md)，使用 `executeTask()`.

```ts
executeTask(async () => {
	try {
		let response = await fetch(callUrl)
		let json = await response.json()
		console.log(json)
	} catch {
		console.log('无法访问 URL')
	}
})
```

fetch 命令还可以包含第二个可选参数，将标头、HTTP 方法和 HTTP 正文打包到一个对象中。

* **url**: 发送请求的地址
* **init**: 一个 `RequestInit` 对象，可能包含：
  * **method** : 要使用的 HTTP 方法（GET、POST、DELETE 等）
  * **body**: 请求正文的内容。它必须以字符串化的 JSON 对象形式发送。
  * **headers**: 要包含在请求中的其他标头。
  * **redirect**: 重定向策略（'follow' | 'error' | 'manual'）
  * **timeout**: 在请求失败前等待响应的时长。默认值为 30000 毫秒（30 秒）。

```ts
executeTask(async () => {
	try {
		let response = await fetch(callUrl, {
			headers: { 'Content-Type': 'application/json' },
			method: 'POST',
			body: JSON.stringify(myBody),
		})
		let json = await response.json()
		console.log(json)
	} catch {
		console.log('无法访问 URL')
	}
})
```

fetch 命令返回一个 `response` 对象，其中包含以下数据：

* `headers`: 一个 `ReadOnlyHeaders` 对象。调用 `get()` 方法以获取特定标头，或调用 `has()` 方法以检查是否存在某个标头。
* `ok`: 布尔值
* `redirected`: 布尔值
* `status`: 状态码数字
* `statusText`: 状态码文本
* `type`: 将具有以下值之一： *basic*, *cors*, *default*, *error*, *opaque*, *opaqueredirect*
* `url`: 已发送的 URL
* `json()`: 以 JSON 格式获取正文。
* `text()`: 以文本形式获取正文。

{% hint style="warning" %}
**📔 注意**: `json()` 和 `text()` 是互斥的。如果你以其中一种格式获取了响应正文，就不能再从 `response` 对象。
{% endhint %}

{% hint style="warning" %}
**📔 注意**: 每个 Decentraland 场景一次只允许执行一个 `fetch` 命令。这不会影响场景代码必须如何组织，因为请求会在内部排队。如果你的场景需要向不同端点发送多个请求，请记住，只有在前一个请求得到响应后，才会发送下一个请求。
{% endhint %}

## 签名请求

你可以采用额外的安全措施来验证请求是否来自 Decentraland 内的玩家会话。你可以发送带有额外签名的请求，该签名使用 Decentraland 会话为每个玩家基于其地址生成的临时密钥进行签名。接收请求的服务器随后可以验证该签名消息确实匹配当前在世界中活跃的地址。

当玩家可能有动机滥用系统、刷取游戏中的代币或积分时，这类安全措施尤其有价值。

要发送签名请求，你只需要使用 `signedFetch()` 函数，方式与使用 `fetch()` 函数。

```ts
import { signedFetch } from '~system/SignedFetch'

executeTask(async () => {
	try {
		let response = await signedFetch({
			url: callUrl,
			init: {
				headers: { 'Content-Type': 'application/json' },
				method: 'POST',
				body: JSON.stringify(myBody),
			},
		})

		if (!response.ok) {
			throw new Error('无效的响应')
		}

		let json = JSON.parse(response.body)

		console.log('已收到响应：', json)
	} catch {
		console.log('无法访问 URL')
	}
})
```

该请求包含额外的一系列标头，其中包含一条签名消息及用于解释它的一组元数据。签名消息由使用玩家临时密钥加密的请求全部内容组成。

该 `signedFetch()` 与 `fetch()` 函数不同，其响应是一个完整 HTTP 消息的 Promise，表示为一个 `FlatFetchResponse` 对象。这包括以下属性：

* `body`
* `headers`
* `ok`
* `status`
* `statusText`

该 **body** 始终是一个字符串，你可以像上面的示例那样对其进行解析。

### 验证签名请求

要使用签名请求，接收这些请求的服务器应当验证签名是否与请求的其余部分匹配，以及签名消息中编码的时间戳是否为当前时间。

你可以在下面的示例场景中找到一个执行此任务的服务器的简单示例：

[验证玩家真实性](https://github.com/decentraland-scenes/validate-player-authenticity)

## 请求超时

如果一个 HTTP 请求等待响应的时间过长，它就会失败，以便可以发送其他请求。对于 `fetch()`，默认超时阈值为 30 秒，但你可以通过配置 `timeout` 属性，为每个请求指定不同的值。的值 `timeout` 以毫秒为单位表示。

```ts
fetch('https://some-url.com', { timeout: 1000 })
```

## 使用 WebSockets

你也可以向 WebSocket 服务器发送和获取数据，只要该服务器使用的是带有 *wss*.

```ts
var socket = new WebSocket('url')

socket.onmessage = function (event) {
	console.log('收到 WebSocket 消息：', event)
}
```

使用 WebSockets 的语法与 JavaScript 原生实现并无不同。有关如何通过 WebSockets 接收和发送消息的详细信息，请参阅 [Mozilla Web API](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) 的文档。

{% hint style="info" %}
**💡 提示**: 有一个简化 websocket 连接使用的库，并且已被证明与 Decentraland 配合良好，那就是 [Colyseus](https://colyseus.io/)。其他一些 websocket 库与 Decentraland SDK 不兼容。

它在 websocket 连接之上构建了一层抽象，使得响应变化以及在服务器端远程存储一致的游戏状态变得非常简单。你可以在这些示例中看到它的实际效果：

* [Cube Jumper](https://github.com/decentraland-scenes/cube-jumper-colyesus-sdk7)
* [Space Traitor](https://github.com/decentraland-scenes/Space-Traitor)
* [AI NPC](https://github.com/decentraland-scenes/inworld-ai-sdk7)
  {% endhint %}

## 调试网络请求

你可以通过打开调试面板来调试网络请求。

要打开调试面板，你可以点击 ![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-92fe4dd70621a496d0da083ae9b5f9b2ef84d2dd%2Fdebug-icon.png?alt=media) 右上角的图标。然后选择 **网络请求** 选项卡并点击 **打开 Chrome 开发者工具**.

这将打开一个新的 Chrome 窗口，并显示已打开的 Network 选项卡。

参见 [在预览中调试](/creator/content-creator-zh/chang-jing-sdk7/tiao-shi/debug-in-preview.md#web-requests) 了解更多详情。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.decentraland.org/creator/content-creator-zh/chang-jing-sdk7/wang-luo/network-connections.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
