websocket.rst 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. .. _doc_websocket:
  2. Using WebSockets
  3. ================
  4. HTML5 and WebSocket
  5. -------------------
  6. The WebSocket protocol was standardized in 2011 with the original goal of allowing browsers to create stable and bidirectional connections with a server.
  7. Before that, browsers used to only support HTTP requests, which aren't well-suited for bidirectional communication.
  8. The protocol is message-based and a very powerful tool to send push notifications to browsers. It has been used to implement chats, turn-based games, and more. It still uses a TCP connection, which is good for reliability but not for latency, so it's not good for real-time applications like VoIP and fast-paced games (see :ref:`WebRTC <doc_webrtc>` for those use cases).
  9. Due to its simplicity, its wide compatibility, and being easier to use than a raw TCP connection, WebSocket started to spread outside the browsers, in native applications as a mean to communicate with network servers.
  10. Godot supports WebSocket in both native and web exports.
  11. Using WebSocket in Godot
  12. ------------------------
  13. WebSocket is implemented in Godot via :ref:`WebSocketPeer <class_WebSocketPeer>`.
  14. The WebSocket implementation is compatible with the High-Level Multiplayer. See
  15. section on :ref:`high-level multiplayer <doc_high_level_multiplayer>` for more
  16. details.
  17. .. warning::
  18. When exporting to Android, make sure to enable the ``INTERNET``
  19. permission in the Android export preset before exporting the project or
  20. using one-click deploy. Otherwise, network communication of any kind will be
  21. blocked by Android.
  22. Minimal client example
  23. ~~~~~~~~~~~~~~~~~~~~~~
  24. This example will show you how to create a WebSocket connection to a remote server, and how to send and receive data.
  25. ::
  26. extends Node
  27. # The URL we will connect to.
  28. # Use "ws://localhost:9080" if testing with the minimal server example below.
  29. # `wss://` is used for secure connections,
  30. # while `ws://` is used for plain text (insecure) connections.
  31. @export var websocket_url = "wss://echo.websocket.org"
  32. # Our WebSocketClient instance.
  33. var socket = WebSocketPeer.new()
  34. func _ready():
  35. # Initiate connection to the given URL.
  36. var err = socket.connect_to_url(websocket_url)
  37. if err == OK:
  38. print("Connecting to %s..." % websocket_url)
  39. # Wait for the socket to connect.
  40. await get_tree().create_timer(2).timeout
  41. # Send data.
  42. print("> Sending test packet.")
  43. socket.send_text("Test packet")
  44. else:
  45. push_error("Unable to connect.")
  46. set_process(false)
  47. func _process(_delta):
  48. # Call this in `_process()` or `_physics_process()`.
  49. # Data transfer and state updates will only happen when calling this function.
  50. socket.poll()
  51. # get_ready_state() tells you what state the socket is in.
  52. var state = socket.get_ready_state()
  53. # `WebSocketPeer.STATE_OPEN` means the socket is connected and ready
  54. # to send and receive data.
  55. if state == WebSocketPeer.STATE_OPEN:
  56. while socket.get_available_packet_count():
  57. var packet = socket.get_packet()
  58. if socket.was_string_packet():
  59. var packet_text = packet.get_string_from_utf8()
  60. print("< Got text data from server: %s" % packet_text)
  61. else:
  62. print("< Got binary data from server: %d bytes" % packet.size())
  63. # `WebSocketPeer.STATE_CLOSING` means the socket is closing.
  64. # It is important to keep polling for a clean close.
  65. elif state == WebSocketPeer.STATE_CLOSING:
  66. pass
  67. # `WebSocketPeer.STATE_CLOSED` means the connection has fully closed.
  68. # It is now safe to stop polling.
  69. elif state == WebSocketPeer.STATE_CLOSED:
  70. # The code will be `-1` if the disconnection was not properly notified by the remote peer.
  71. var code = socket.get_close_code()
  72. print("WebSocket closed with code: %d. Clean: %s" % [code, code != -1])
  73. set_process(false) # Stop processing.
  74. This will print something similar to:
  75. .. highlight:: none
  76. ::
  77. Connecting to wss://echo.websocket.org...
  78. < Got text data from server: Request served by 7811941c69e658
  79. > Sending test packet.
  80. < Got text data from server: Test packet
  81. Minimal server example
  82. ~~~~~~~~~~~~~~~~~~~~~~
  83. This example will show you how to create a WebSocket server that listens for remote connections, and how to send and receive data.
  84. .. highlight:: gdscript
  85. ::
  86. extends Node
  87. # The port we will listen to.
  88. const PORT = 9080
  89. # Our TCP Server instance.
  90. var _tcp_server = TCPServer.new()
  91. # Our connected peers list.
  92. var _peers: Dictionary[int, WebSocketPeer] = {}
  93. var last_peer_id := 1
  94. func _ready():
  95. # Start listening on the given port.
  96. var err = _tcp_server.listen(PORT)
  97. if err == OK:
  98. print("Server started.")
  99. else:
  100. push_error("Unable to start server.")
  101. set_process(false)
  102. func _process(_delta):
  103. while _tcp_server.is_connection_available():
  104. last_peer_id += 1
  105. print("+ Peer %d connected." % last_peer_id)
  106. var ws = WebSocketPeer.new()
  107. ws.accept_stream(_tcp_server.take_connection())
  108. _peers[last_peer_id] = ws
  109. # Iterate over all connected peers using "keys()" so we can erase in the loop
  110. for peer_id in _peers.keys():
  111. var peer = _peers[peer_id]
  112. peer.poll()
  113. var peer_state = peer.get_ready_state()
  114. if peer_state == WebSocketPeer.STATE_OPEN:
  115. while peer.get_available_packet_count():
  116. var packet = peer.get_packet()
  117. if peer.was_string_packet():
  118. var packet_text = packet.get_string_from_utf8()
  119. print("< Got text data from peer %d: %s ... echoing" % [peer_id, packet_text])
  120. # Echo the packet back.
  121. peer.send_text(packet_text)
  122. else:
  123. print("< Got binary data from peer %d: %d ... echoing" % [peer_id, packet.size()])
  124. # Echo the packet back.
  125. peer.send(packet)
  126. elif peer_state == WebSocketPeer.STATE_CLOSED:
  127. # Remove the disconnected peer.
  128. _peers.erase(peer_id)
  129. var code = peer.get_close_code()
  130. var reason = peer.get_close_reason()
  131. print("- Peer %s closed with code: %d, reason %s. Clean: %s" % [peer_id, code, reason, code != -1])
  132. When a client connects, this will print something similar to this:
  133. .. highlight:: none
  134. ::
  135. Server started.
  136. + Peer 2 connected.
  137. < Got text data from peer 2: Test packet ... echoing
  138. Advanced chat demo
  139. ~~~~~~~~~~~~~~~~~~
  140. A more advanced chat demo which optionally uses the multiplayer mid-level
  141. abstraction and a high-level multiplayer demo are available in the
  142. `godot demo projects <https://github.com/godotengine/godot-demo-projects>`_
  143. under `networking/websocket_chat` and `networking/websocket_multiplayer`.