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...
Использование WebSockets
HTML5 и WebSocket
Протокол WebSocket был стандартизирован в 2011 году с первоначальной целью — позволить браузерам создавать стабильные двунаправленные соединения с сервером. До этого браузеры поддерживали только HTTP-запросы, которые плохо подходили для двунаправленной связи.
Этот протокол основан на сообщениях и представляет собой очень мощный инструмент для отправки push-уведомлений в браузеры. Он использовался для реализации чатов, пошаговых игр и многого другого. Он по-прежнему использует TCP-соединение, что обеспечивает надёжность, но не уменьшает задержку, поэтому не подходит для приложений реального времени, таких как VoIP и динамичные игры (см. WebRTC для получения информации об этих вариантах использования).
Благодаря своей простоте, широкой совместимости и простоте использования по сравнению с обычным TCP-соединением, WebSocket начал распространяться за пределами браузеров, в собственных приложениях как средство связи с сетевыми серверами.
Godot поддерживает WebSocket как при нативном, так и при веб-экспорте.
WebSocket в контексте Godot
WebSocket реализован в Godot через WebSocketPeer. Эта реализация совместима с высокоуровневой многопользовательской системой. Подробнее см. раздел high-level multiplayer.
Предупреждение
При экспорте под Android обязательно включите разрешение INTERNET в пресете экспорта Android до экспорта проекта или использования одноразвёртывания. Иначе любое сетевое взаимодействие будет заблокировано системой 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 по путям networking/websocket_chat и networking/websocket_multiplayer.