Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
使用 WebSocket
HTML5 与 WebSocket
WebSocket 协议在 2011 年被标准化,最初的目标是让浏览器与服务器建立稳定的双向连接。在此之前,浏览器只支持 HTTP 请求,而这并不适合双向通信。
该协议是基于消息的,是一种可向浏览器发送推送通知的非常强大的工具,并且已经被用于实现聊天、回合制游戏等。它仍然使用 TCP 连接,这对可靠性有好处,但对延迟不利,因此不适合实时应用,如 VoIP 和快节奏的游戏(有关这些用例,请参阅 WebRTC)。
由于其简单性、广泛的兼容性以及比原始 TCP 连接更容易使用,WebSocket 很快就开始在浏览器之外的地方应用,在原生应用程序中作为与网络服务器通信的一种手段。
Godot 在原生导出和 Web 导出中都支持 WebSocket。
在 Godot 中使用 WebSocket
在 Godot 中,WebSocket 通过 WebSocketPeer 实现。WebSocket 实现与高阶多人游戏兼容。有关更多详细信息,请参阅《高阶多人游戏》章节。
警告
导出到 Android 时,在导出项目或使用一键部署之前,确保在 Android 导出预设中启用 INTERNET 权限。否则,Android 系统会阻止该程序的任何网络通信。
最小客户端示例
这个示例演示的是如何建立与远程服务器的 WebSocket 连接,以及如何收发数据。
extends Node
# The URL we will connect to.
# Use "ws://localhost:9080" if testing with the minimal server example below.
# `wss://` is used for secure connections,
# while `ws://` is used for plain text (insecure) connections.
@export var websocket_url = "wss://echo.websocket.org"
# Our WebSocketClient instance.
var socket = WebSocketPeer.new()
func _ready():
# Initiate connection to the given URL.
var err = socket.connect_to_url(websocket_url)
if err == OK:
print("Connecting to %s..." % websocket_url)
# Wait for the socket to connect.
await get_tree().create_timer(2).timeout
# Send data.
print("> Sending test packet.")
socket.send_text("Test packet")
else:
push_error("Unable to connect.")
set_process(false)
func _process(_delta):
# Call this in `_process()` or `_physics_process()`.
# Data transfer and state updates will only happen when calling this function.
socket.poll()
# get_ready_state() tells you what state the socket is in.
var state = socket.get_ready_state()
# `WebSocketPeer.STATE_OPEN` means the socket is connected and ready
# to send and receive data.
if state == WebSocketPeer.STATE_OPEN:
while socket.get_available_packet_count():
var packet = socket.get_packet()
if socket.was_string_packet():
var packet_text = packet.get_string_from_utf8()
print("< Got text data from server: %s" % packet_text)
else:
print("< Got binary data from server: %d bytes" % packet.size())
# `WebSocketPeer.STATE_CLOSING` means the socket is closing.
# It is important to keep polling for a clean close.
elif state == WebSocketPeer.STATE_CLOSING:
pass
# `WebSocketPeer.STATE_CLOSED` means the connection has fully closed.
# It is now safe to stop polling.
elif state == WebSocketPeer.STATE_CLOSED:
# The code will be `-1` if the disconnection was not properly notified by the remote peer.
var code = socket.get_close_code()
print("WebSocket closed with code: %d. Clean: %s" % [code, code != -1])
set_process(false) # Stop processing.
这个示例会打印类似这样的内容:
Connecting to wss://echo.websocket.org...
< Got text data from server: Request served by 7811941c69e658
> Sending test packet.
< Got text data from server: Test packet
最小服务器示例
这个例子将告诉你如何创建一个监听远程连接的WebSocket服务器,以及如何发送和接收数据。
extends Node
# The port we will listen to.
const PORT = 9080
# Our TCP Server instance.
var _tcp_server = TCPServer.new()
# Our connected peers list.
var _peers: Dictionary[int, WebSocketPeer] = {}
var last_peer_id := 1
func _ready():
# Start listening on the given port.
var err = _tcp_server.listen(PORT)
if err == OK:
print("Server started.")
else:
push_error("Unable to start server.")
set_process(false)
func _process(_delta):
while _tcp_server.is_connection_available():
last_peer_id += 1
print("+ Peer %d connected." % last_peer_id)
var ws = WebSocketPeer.new()
ws.accept_stream(_tcp_server.take_connection())
_peers[last_peer_id] = ws
# Iterate over all connected peers using "keys()" so we can erase in the loop
for peer_id in _peers.keys():
var peer = _peers[peer_id]
peer.poll()
var peer_state = peer.get_ready_state()
if peer_state == WebSocketPeer.STATE_OPEN:
while peer.get_available_packet_count():
var packet = peer.get_packet()
if peer.was_string_packet():
var packet_text = packet.get_string_from_utf8()
print("< Got text data from peer %d: %s ... echoing" % [peer_id, packet_text])
# Echo the packet back.
peer.send_text(packet_text)
else:
print("< Got binary data from peer %d: %d ... echoing" % [peer_id, packet.size()])
# Echo the packet back.
peer.send(packet)
elif peer_state == WebSocketPeer.STATE_CLOSED:
# Remove the disconnected peer.
_peers.erase(peer_id)
var code = peer.get_close_code()
var reason = peer.get_close_reason()
print("- Peer %s closed with code: %d, reason %s. Clean: %s" % [peer_id, code, reason, code != -1])
当客户端连接时,这将打印出类似这样的内容:
Server started.
+ Peer 2 connected.
< Got text data from peer 2: Test packet ... echoing
高级聊天演示
在 godot demo projects 的 networking/websocket_chat 和 networking/websocket_multiplayer 中有一个更高级的聊天演示,可以选择使用多人游戏中阶抽象,还有一个高阶多人游戏演示。