WebSocket

HTML5 und WebSocket

Das WebSocket-Protokoll wurde 2011 mit dem ursprünglichen Ziel standardisiert, dass Browser stabile und bidirektionale Verbindungen mit einem Server herstellen können. Zuvor unterstützten Browser nur HTTPRequests, was für die bidirektionale Kommunikation nicht gut geeignet ist.

Das Protokoll ist recht einfach, nachrichtenbasiert und ein sehr leistungsfähiges Tool zum Senden von Push-Benachrichtigungen an Browser. Es wurde zum Implementieren von Chats, rundenbasierten Spielen usw. verwendet. Es verwendet weiterhin eine TCP-Verbindung, die für die Zuverlässigkeit gut ist, jedoch nicht Die Latenz ist also nicht gut für Echtzeitanwendungen wie VoIP und schnelle Spiele (siehe WebRTC für diese Anwendungsfälle).

Aufgrund seiner Einfachheit, seiner breiten Kompatibilität und seiner einfacheren Verwendung als eine rohe TCP-Verbindung verbreitete sich WebSocket bald außerhalb der Browser in nativen Anwendungen, um mit Netzwerkservern zu kommunizieren.

Godot unterstützt WebSocket sowohl beim nativen als auch beim HTML5-Export.

Verwenden von WebSocket in Godot

WebSocket wird in Godot über drei Hauptklassen implementiert WebSocketClient , WebSocketServer und WebSocketPeer. Die WebSocket-Implementierung ist mit dem High-Level Mehrspieler kompatibel. Weitere Informationen finden Sie im Abschnitt über High-Level-Multiplayer.

Warnung

When exporting to Android, make sure to enable the INTERNET permission in the Android export preset before exporting the project or using one-click deploy. Otherwise, network communication of any kind will be blocked by Android.

minimales Client Beispiel

In diesem Beispiel wird gezeigt, wie Sie eine WebSocket-Verbindung zu einem Remoteserver herstellen und Daten senden und empfangen.

extends Node

# The URL we will connect to
export var websocket_url = "wss://libwebsockets.org"

# Our WebSocketClient instance
var _client = WebSocketClient.new()

func _ready():
    # Connect base signals to get notified of connection open, close, and errors.
    _client.connect("connection_closed", self, "_closed")
    _client.connect("connection_error", self, "_closed")
    _client.connect("connection_established", self, "_connected")
    # This signal is emitted when not using the Multiplayer API every time
    # a full packet is received.
    # Alternatively, you could check get_peer(1).get_available_packets() in a loop.
    _client.connect("data_received", self, "_on_data")

    # Initiate connection to the given URL.
    var err = _client.connect_to_url(websocket_url, ["lws-mirror-protocol"])
    if err != OK:
        print("Unable to connect")
        set_process(false)

func _closed(was_clean = false):
    # was_clean will tell you if the disconnection was correctly notified
    # by the remote peer before closing the socket.
    print("Closed, clean: ", was_clean)
    set_process(false)

func _connected(proto = ""):
    # This is called on connection, "proto" will be the selected WebSocket
    # sub-protocol (which is optional)
    print("Connected with protocol: ", proto)
    # You MUST always use get_peer(1).put_packet to send data to server,
    # and not put_packet directly when not using the MultiplayerAPI.
    _client.get_peer(1).put_packet("Test packet".to_utf8())

func _on_data():
    # Print the received packet, you MUST always use get_peer(1).get_packet
    # to receive data from server, and not get_packet directly when not
    # using the MultiplayerAPI.
    print("Got data from server: ", _client.get_peer(1).get_packet().get_string_from_utf8())

func _process(delta):
    # Call this in _process or _physics_process. Data transfer, and signals
    # emission will only happen when calling this function.
    _client.poll()

Dies zeigt:

Connected with protocol:
Got data from server: Test packet

kleines Server Beispiel

This example will show you how to create a WebSocket server that listens for remote connections, and how to send and receive data.

extends Node

# The port we will listen to
const PORT = 9080
# Our WebSocketServer instance
var _server = WebSocketServer.new()

func _ready():
    # Connect base signals to get notified of new client connections,
    # disconnections, and disconnect requests.
    _server.connect("client_connected", self, "_connected")
    _server.connect("client_disconnected", self, "_disconnected")
    _server.connect("client_close_request", self, "_close_request")
    # This signal is emitted when not using the Multiplayer API every time a
    # full packet is received.
    # Alternatively, you could check get_peer(PEER_ID).get_available_packets()
    # in a loop for each connected peer.
    _server.connect("data_received", self, "_on_data")
    # Start listening on the given port.
    var err = _server.listen(PORT)
    if err != OK:
        print("Unable to start server")
        set_process(false)

func _connected(id, proto):
    # This is called when a new peer connects, "id" will be the assigned peer id,
    # "proto" will be the selected WebSocket sub-protocol (which is optional)
    print("Client %d connected with protocol: %s" % [id, proto])

func _close_request(id, code, reason):
    # This is called when a client notifies that it wishes to close the connection,
    # providing a reason string and close code.
    print("Client %d disconnecting with code: %d, reason: %s" % [id, code, reason])

func _disconnected(id, was_clean = false):
    # This is called when a client disconnects, "id" will be the one of the
    # disconnecting client, "was_clean" will tell you if the disconnection
    # was correctly notified by the remote peer before closing the socket.
    print("Client %d disconnected, clean: %s" % [id, str(was_clean)])

func _on_data(id):
    # Print the received packet, you MUST always use get_peer(id).get_packet to receive data,
    # and not get_packet directly when not using the MultiplayerAPI.
    var pkt = _server.get_peer(id).get_packet()
    print("Got data from client %d: %s ... echoing" % [id, pkt.get_string_from_utf8()])
    _server.get_peer(id).put_packet(pkt)

func _process(delta):
    # Call this in _process or _physics_process.
    # Data transfer, and signals emission will only happen when calling this function.
    _server.poll()

Dadurch wird (wenn ein Client eine Verbindung herstellt) etwas Ähnliches wie hier gedruckt:

Client 1348090059 connected with protocol: selected-protocol
Got data from client 1348090059: Test packet ... echoing

fortgeschrittenes Chat Demo

Eine erweiterte Chat-Demo, die optional die Multiplayer-Mid-Level-Abstraktion und eine High-Level-Multiplayer-Demo verwendet, ist in den godot-Demo-Projekten unter Networking/websocket_chat und networking/websocket_multiplayer verfügbar.