Minecraft:RakNet: Difference between revisions
More actions
Sync: updated from Minecraft |
Sync: updated from Minecraft |
||
| (6 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
{{Exclusive|bedrock}} | {{Exclusive|bedrock}} | ||
'''RakNet''' is a networking library and protocol for multiplayer games. It runs over [[Minecraft:wikipedia:User_Datagram_Protocol|UDP]] and provides connection management, configurable reliability and ordering, sequencing, and fragmentation. | |||
[[Minecraft:wikipedia:User_Datagram_Protocol|UDP]] does not guarantee delivery or ordering. RakNet supports different delivery modes, so applications can request reliability or ordering when needed. | |||
The source code for RakNet is available in the [https://github.com/facebookarchive/RakNet archived source repository]. | |||
== Use in Bedrock Edition == | |||
[[Minecraft:NetherNet]] became the default transport for [[Minecraft:Bedrock Dedicated Server]] in [[Minecraft:26.50]].<ref>{{cite|url=https://www.minecraft.net/en-us/article/minecraft--bedrock-edition-26-50-changelog|title=Minecraft: Bedrock Edition 26.50 Changelog|website=Minecraft.net}}</ref> RakNet is deprecated in [[Minecraft:26.60]], which removes client support for it.<ref>{{cite|url=https://feedback.minecraft.net/hc/en-us/articles/48740748263565-Minecraft-Beta-Preview-26-60-22-23|title=Minecraft Beta & Preview - 26.60.22/23|website=Minecraft Feedback}}</ref> | |||
== Libraries == | == Libraries == | ||
The following libraries implement RakNet. Supported features and protocol versions vary between implementations. | |||
{| class="wikitable sortable" style="width: auto; text-align: center;" | {| class="wikitable sortable" style="width: auto; text-align: center;" | ||
| Line 15: | Line 20: | ||
! Language | ! Language | ||
! License | ! License | ||
|- | |- | ||
! [https://github.com/sandertv/go-raknet go-raknet] | ! [https://github.com/sandertv/go-raknet go-raknet] | ||
| | | style="text-align: left;" | RakNet implementation written in Go. | ||
| | | Go | ||
| MIT | | MIT | ||
|- | |- | ||
! [https://github.com/ | ! [https://github.com/NetrexMC/RakNet RakNet] | ||
| RakNet implementation written in Rust. | | style="text-align: left;" | Asynchronous RakNet implementation written in Rust. | ||
| Rust | | Rust | ||
| Apache | | Apache-2.0 | ||
|- | |- | ||
! [https://github.com/PieMC-Dev/PieRakNet PieRakNet] | ! [https://github.com/PieMC-Dev/PieRakNet PieRakNet] | ||
| | | style="text-align: left;" | RakNet implementation written in Python. | ||
| Python | | Python | ||
| GPL-3 | | GPL-3.0 | ||
|- | |- | ||
! [https://github.com/ | ! [https://github.com/CloudburstMC/Network Cloudburst Network] | ||
| Network components used | | style="text-align: left;" | Network components used by CloudburstMC projects. | ||
| Java | | Java | ||
| Apache | | Apache-2.0 | ||
|- | |- | ||
! [https://github.com/Podrum/rak_net rak-net] | ! [https://github.com/Podrum/rak_net rak-net] | ||
| | | style="text-align: left;" | Python RakNet implementation originally developed for Podrum. | ||
| Python | | Python | ||
| GPL | | GPL-2.0 | ||
|- | |- | ||
! [https://github.com/ | ! [https://github.com/whirvis/JRakNet JRakNet] | ||
| | | style="text-align: left;" | Java implementation of the RakNet protocol. | ||
| Java | | Java | ||
| MIT | | MIT | ||
|- | |- | ||
! [https://github.com/yesdog/netty-raknet netty-raknet] | ! [https://github.com/yesdog/netty-raknet netty-raknet] | ||
| | | style="text-align: left;" | RakNet implementation for Netty. | ||
| Java | | Java | ||
| MIT | | MIT | ||
|- | |- | ||
! [https://github.com/ | ! [https://github.com/alejzeis/JRakLibPlus JRakLibPlus] | ||
| | | style="text-align: left;" | RakNet server library based on RakLib and JRakLib. | ||
| Java | | Java | ||
| LGPL | | LGPL-3.0 | ||
|- | |||
|- | |||
! [https://github.com/pmmp/RakLib RakLib] | ! [https://github.com/pmmp/RakLib RakLib] | ||
| RakNet server implementation | | style="text-align: left;" | Lightweight PHP RakNet server implementation. | ||
| PHP | | PHP | ||
| GPL | | GPL-3.0 | ||
|- | |||
|- | |||
! [https://www.npmjs.com/package/raknet/ raknet] | ! [https://www.npmjs.com/package/raknet/ raknet] | ||
| UDP | | style="text-align: left;" | UDP networking library for Node.js that follows the RakNet protocol. | ||
| | | JavaScript | ||
| MIT | | MIT | ||
|- | |- | ||
! [https://pypi.org/project/PyRakLib/ PyRakLib] | ! [https://pypi.org/project/PyRakLib/ PyRakLib] | ||
| | | style="text-align: left;" | Python port of RakLib that follows the RakNet protocol. | ||
| Python | | Python | ||
| GPL | | GPL | ||
|- | |||
|- | |||
! [https://github.com/b23r0/rust-raknet rust-raknet] | ! [https://github.com/b23r0/rust-raknet rust-raknet] | ||
| RakNet | | style="text-align: left;" | RakNet implementation written in Rust. | ||
| Rust | | Rust | ||
| MIT | | MIT | ||
|- | |- | ||
! [https://github.com/SerenityJS/Baltica Baltica] | |||
| | | style="text-align: left;" | Bedrock toolkit that includes a RakNet implementation. | ||
|TypeScript | | TypeScript | ||
| | | See repository | ||
|- | |||
|- | |||
! [https://github.com/mfdgaming/raknet.py RakNet.Py] | ! [https://github.com/mfdgaming/raknet.py RakNet.Py] | ||
| | | style="text-align: left;" | RakNet implementation written in Python. | ||
| Python | | Python | ||
| GPL | | GPL-2.0 | ||
|- | |- | ||
![https://github.com/LavishMC/ | ! [https://github.com/LavishMC/RakNet LavishMC RakNet] | ||
| | | style="text-align: left;" | C++ fork of the original RakNet implementation. | ||
|C++ | |||
| C++ | | C++ | ||
| BSD | | BSD | ||
| | |- | ||
! [https://github.com/facebookarchive/RakNet RakNet (original)] | |||
| style="text-align: left;" | Original C++ RakNet implementation. | |||
| C++ | |||
| BSD-2-Clause | |||
|} | |} | ||
== Data types == | == Data types == | ||
The types below describe the packet layouts on this page. Multi-byte integers are big-endian unless stated otherwise; 24-bit indices are little-endian. Address structures have their own byte order.<ref>[https://github.com/facebookarchive/RakNet/blob/master/Source/BitStream.h RakNet: BitStream] [https://github.com/Sandertv/go-raknet/blob/master/packet.go go-raknet: Frame encoding]</ref> | |||
{| class="wikitable" | {| class="wikitable" | ||
! Type !! Size !! Description | |||
! | |||
! | |||
|- | |- | ||
! Byte | |||
|byte | | 1 byte | ||
| | | Unsigned 8-bit value. | ||
|- | |- | ||
! Boolean | |||
|byte | | 1 byte | ||
| | | {{cd|0x00}} is false; {{cd|0x01}} is true. | ||
| | |||
|- | |- | ||
! Short | |||
| | | 2 bytes | ||
| | | Signed 16-bit integer. | ||
|- | |- | ||
! Unsigned Short | |||
| | | 2 bytes | ||
| | | Unsigned 16-bit integer. | ||
|- | |- | ||
! Int | |||
| | | 4 bytes | ||
| | | Signed 32-bit integer. | ||
|- | |- | ||
! Unsigned Int | |||
| | | 4 bytes | ||
| | | Unsigned 32-bit integer. | ||
|- | |- | ||
! Long | |||
| | | 8 bytes | ||
| | | 64-bit integer. Whether it represents a signed value depends on the field. | ||
|- | |- | ||
! uint24le | |||
| | | 3 bytes | ||
| | | Unsigned 24-bit little-endian integer, used for datagram sequence numbers and frame indices. | ||
|- | |- | ||
! String | |||
| | | Variable | ||
| | | An unsigned 16-bit byte length followed by that many string bytes. | ||
|- | |- | ||
! | ! Magic | ||
| | | 16 bytes | ||
| | | The fixed {{cd|00ffff00fefefefefdfdfdfd12345678}} value used in offline packets.<ref>[https://github.com/facebookarchive/RakNet/blob/master/Source/RakPeer.cpp RakNet: RakPeer.cpp]</ref> | ||
| | |||
|- | |- | ||
! | ! Address | ||
| | | 7 bytes (IPv4);<br/>29 bytes (IPv6) | ||
| | | Encodes the address family, address and port. IPv4 address bytes are inverted; the port is big-endian. IPv6 also includes address-family, flow-info and scope fields.<ref name="address-format">[https://github.com/Sandertv/go-raknet/blob/master/internal/message/addr.go go-raknet: Address encoding]</ref> | ||
|} | |} | ||
== Handshake sequence == | == Handshake sequence == | ||
The handshake begins with unconnected UDP packets and continues with connection-control messages carried inside RakNet frames.<ref>[https://github.com/facebookarchive/RakNet/blob/master/Source/RakPeer.cpp RakNet: RakPeer.cpp] [https://github.com/Sandertv/go-raknet/tree/master/internal/message go-raknet: Connection messages]</ref> | |||
# C→S: [[#Open Connection Request 1|Open Connection Request 1]] | # C→S: [[#Open Connection Request 1|Open Connection Request 1]] | ||
# S→C: [[#Open Connection Reply 1|Open Connection Reply 1]] | # S→C: [[#Open Connection Reply 1|Open Connection Reply 1]] (or [[#Incompatible Protocol|Incompatible Protocol]]) | ||
# C→S: [[#Open Connection Request 2|Open Connection Request 2]] | # C→S: [[#Open Connection Request 2|Open Connection Request 2]] | ||
# S→C: [[#Open Connection Reply 2|Open Connection Reply 2]] | # S→C: [[#Open Connection Reply 2|Open Connection Reply 2]]. The peers can now exchange framed connection-control messages. | ||
# C→S: [[#Connection Request|Connection Request]] | # C→S: [[#Connection Request|Connection Request]] | ||
# S→C: [[#Connection Request Accepted|Connection Request Accepted]] | # S→C: [[#Connection Request Accepted|Connection Request Accepted]] | ||
# C→S: [[#New Incoming Connection|New Incoming Connection]] | # C→S: [[#New Incoming Connection|New Incoming Connection]] | ||
After this exchange, the RakNet connection is established. Connection Request, Connection Request Accepted, and New Incoming Connection are themselves carried inside frames. In [[Minecraft:Bedrock Edition]], game packets are carried in RakNet frames as described at [[#Game Packet|Game Packet]]. | |||
== Packets == | == Packets == | ||
Offline packet IDs identify UDP datagrams; connected message IDs identify the payload inside a frame. The handshake tables below describe the layout with RakNet security disabled. Optional security handshakes and connection passwords are not included. Field details can vary by implementation.<ref>[https://github.com/facebookarchive/RakNet/blob/master/Source/MessageIdentifiers.h RakNet: Message identifiers] [https://github.com/Sandertv/go-raknet/blob/master/packet.go go-raknet: Frame encoding]</ref> | |||
=== Unconnected Ping === | === Unconnected Ping === | ||
The client sends this packet to discover a server. ID {{cd|0x01}} is a regular unconnected ping; {{cd|0x02}} asks for a response only when the server is accepting new connections. The server replies with [[#Unconnected Pong|Unconnected Pong]]. | |||
{| class="wikitable" | {| class="wikitable" | ||
! Packet ID | ! Packet ID | ||
! Field Name | ! Field Name | ||
! Field Type | ! Field Type | ||
|- | |- | ||
|rowspan="3"| 0x01, 0x02 | |rowspan="3"| 0x01, 0x02 | ||
| Time | | Time | ||
| Long | | Long | ||
|- | |- | ||
| | | Magic | ||
| Magic | |||
| | |||
|- | |- | ||
| Client GUID | | Client GUID | ||
| Long | | Long | ||
|} | |} | ||
=== Unconnected Pong === | |||
The server sends this in response to an unconnected ping. It echoes the ping time and includes its GUID and a server ID string. In [[Minecraft:Bedrock Edition]], that string contains server-list information in a semicolon-delimited format; its fields can vary by game version. | |||
{| class="wikitable" | {| class="wikitable" | ||
! Packet ID | ! Packet ID | ||
| Line 296: | Line 211: | ||
| | | | ||
|- | |- | ||
| | | Magic | ||
| | | Magic | ||
| | | | ||
|- | |- | ||
| Server ID String | | Server ID String | ||
| | | String | ||
| | | Carries server-list information. | ||
|} | |} | ||
=== Connected Ping === | |||
This packet measures latency on an established connection. It is commonly sent unreliably. | |||
{| class="wikitable" | {| class="wikitable" | ||
| Line 324: | Line 228: | ||
! Field Name | ! Field Name | ||
! Field Type | ! Field Type | ||
|- | |- | ||
| 0x00 | | 0x00 | ||
| Time | | Time | ||
| Long | | Long | ||
|} | |} | ||
=== Connected Pong === | |||
The receiver replies with the original ping time and its own response time. It is commonly sent unreliably. | |||
{| class="wikitable" | {| class="wikitable" | ||
! Packet ID | ! Packet ID | ||
! Field Name | ! Field Name | ||
! Field Type | ! Field Type | ||
|- | |- | ||
|rowspan="2"| 0x03 | |rowspan="2"| 0x03 | ||
| Ping Time | | Ping Time | ||
| Long | | Long | ||
|- | |- | ||
| Pong Time | | Pong Time | ||
| Long | | Long | ||
|} | |} | ||
=== Open Connection Request 1 === | |||
The first packet in the handshake sequence, sent by the client to the server. | The first packet in the handshake sequence, sent by the client to the server. | ||
{| class="wikitable" | {| class="wikitable" | ||
! Packet ID | ! Packet ID | ||
| Line 364: | Line 263: | ||
|rowspan="3"| 0x05 | |rowspan="3"| 0x05 | ||
| Magic | | Magic | ||
| | | Magic | ||
| | | | ||
|- | |- | ||
| Protocol version | | Protocol version | ||
| | | Byte | ||
| | | RakNet protocol version used by the client; separate from the Bedrock game protocol version. | ||
|- | |- | ||
| | | Padding | ||
| Zero | | Zero bytes | ||
| | | Zero padding used to probe the path [[Minecraft:wikipedia:Maximum_transmission_unit|MTU]]. | ||
|} | |} | ||
The | The MTU is inferred from the datagram length, including IP and UDP overhead; it is not a numeric field in this request. The server replies with the selected MTU, or sends [[#Incompatible Protocol|Incompatible Protocol]] if it does not support the client's RakNet protocol version. | ||
=== Open Connection Reply 1 === | === Open Connection Reply 1 === | ||
The second packet in the handshake sequence, sent by the server to the client. | The second packet in the handshake sequence, sent by the server to the client. | ||
{| class="wikitable" | {| class="wikitable" | ||
! Packet ID | ! Packet ID | ||
| Line 387: | Line 287: | ||
! Notes | ! Notes | ||
|- | |- | ||
|rowspan=" | |rowspan="4"| 0x06 | ||
| Magic | |||
| Magic | | Magic | ||
| | | | ||
|- | |- | ||
| Line 397: | Line 297: | ||
|- | |- | ||
| Use security | | Use security | ||
| | | Boolean | ||
| | | False for the layout shown here. | ||
|- | |- | ||
| MTU | | MTU | ||
| Unsigned | | Unsigned Short | ||
| | | Selected MTU for the connection. | ||
|} | |} | ||
=== Open Connection Request 2 === | === Open Connection Request 2 === | ||
The third packet in the handshake sequence, sent by the client to the server. | The third packet in the handshake sequence, sent by the client to the server. | ||
{| class="wikitable" | {| class="wikitable" | ||
! Packet ID | ! Packet ID | ||
! Field Name | ! Field Name | ||
! Field Type | ! Field Type | ||
|- | |- | ||
|rowspan=" | |rowspan="4"| 0x07 | ||
| Magic | |||
| Magic | | Magic | ||
|- | |- | ||
| | | Server Address | ||
| | | Address | ||
|- | |- | ||
| MTU | | MTU | ||
| | | Unsigned Short | ||
|- | |||
|- | |||
| Client GUID | | Client GUID | ||
| Long | | Long | ||
|} | |} | ||
=== Open Connection Reply 2 === | === Open Connection Reply 2 === | ||
The fourth packet in the handshake sequence, sent by the server to the client. | The fourth packet in the handshake sequence, sent by the server to the client. | ||
{| class="wikitable" | {| class="wikitable" | ||
! Packet ID | ! Packet ID | ||
| Line 456: | Line 340: | ||
|rowspan="5"| 0x08 | |rowspan="5"| 0x08 | ||
| Magic | | Magic | ||
| | | Magic | ||
| | | | ||
|- | |- | ||
| Line 464: | Line 348: | ||
|- | |- | ||
| Client Address | | Client Address | ||
| | | Address | ||
| | | | ||
|- | |- | ||
| MTU | | MTU | ||
| | | Unsigned Short | ||
| | | | ||
|- | |- | ||
| Encryption enabled | | Encryption enabled | ||
| | | Boolean | ||
| | | False for the layout shown here. | ||
|} | |} | ||
=== Connection Request === | === Connection Request === | ||
The client sends this framed message after Open Connection Reply 2 to continue the RakNet handshake. | |||
{| class="wikitable" | {| class="wikitable" | ||
! Packet ID | ! Packet ID | ||
! Field Name | ! Field Name | ||
! Field Type | ! Field Type | ||
|- | |- | ||
|rowspan="3"| 0x09 | |rowspan="3"| 0x09 | ||
| GUID | | GUID | ||
| Long | | Long | ||
|- | |- | ||
| Time | | Time | ||
| Long | | Long | ||
|- | |- | ||
| Use security | | Use security | ||
| | | Boolean | ||
|} | |} | ||
=== Connection Request Accepted === | === Connection Request Accepted === | ||
The server sends this packet to accept the client's connection request. | |||
{| class="wikitable" | {| class="wikitable" | ||
! Packet ID | ! Packet ID | ||
| Line 506: | Line 392: | ||
|rowspan="5"| 0x10 | |rowspan="5"| 0x10 | ||
| Client address | | Client address | ||
| | | Address | ||
| | | | ||
|- | |- | ||
| System index | | System index | ||
| | | Unsigned Short | ||
| | | System index assigned by the server. | ||
|- | |- | ||
| Internal | | Internal addresses | ||
| | | Address array | ||
| | | Internal server addresses; the count varies by implementation, commonly 10 or 20.<ref name="accepted-addresses">[https://github.com/Sandertv/go-raknet/blob/master/internal/message/connection_request_accepted.go go-raknet: Connection Request Accepted]</ref> | ||
|- | |- | ||
| Request time | | Request time | ||
| Long | | Long | ||
| | | Timestamp from the corresponding [[#Connection Request|Connection Request]]. | ||
|- | |- | ||
| Time | | Time | ||
| Long | | Long | ||
| | | Server acceptance time. | ||
|} | |} | ||
=== New Incoming Connection === | === New Incoming Connection === | ||
The client sends this packet to confirm that it received the server's acceptance. | |||
{| class="wikitable" | {| class="wikitable" | ||
! Packet ID | ! Packet ID | ||
| Line 535: | Line 424: | ||
|rowspan="4"| 0x13 | |rowspan="4"| 0x13 | ||
| Server address | | Server address | ||
| | | Address | ||
| | | | ||
|- | |- | ||
| Internal | | Internal addresses | ||
| | | Address array | ||
| | | Internal client addresses; the count varies by implementation, commonly 10 or 20.<ref>[https://github.com/Sandertv/go-raknet/blob/master/internal/message/new_incoming_connection.go go-raknet: New Incoming Connection]</ref> | ||
|- | |- | ||
| | | Ping time | ||
| Long | | Long | ||
| | | Server acceptance timestamp echoed by the client. | ||
|- | |- | ||
| | | Pong time | ||
| Long | | Long | ||
| | | Time at which the client sends this message. | ||
|} | |} | ||
=== | === Disconnection Notification === | ||
This packet notifies the other peer that the sender is disconnecting. | |||
{| class="wikitable" | {| class="wikitable" | ||
! Packet ID !! Field Name !! Field Type !! Notes | |||
|- | |||
| 0x15 || colspan="2" | No payload || Signals that the sender is disconnecting. | |||
|} | |||
=== Incompatible Protocol === | === Incompatible Protocol === | ||
The server sends this packet when it does not support the RakNet protocol version used by the client. | |||
{| class="wikitable" | {| class="wikitable" | ||
! Packet ID | ! Packet ID | ||
! Field Name | ! Field Name | ||
! Field Type | ! Field Type | ||
|- | |- | ||
|rowspan="3"| 0x19 | |rowspan="3"| 0x19 | ||
| Protocol | | Protocol | ||
| | | Byte | ||
|- | |- | ||
| Magic | | Magic | ||
| | | Magic | ||
|- | |- | ||
| Server GUID | | Server GUID | ||
| Long | | Long | ||
|} | |} | ||
=== | === Frame Set Packet === | ||
This packet carries one or more frames between connected peers. | |||
{| class="wikitable" | {| class="wikitable" | ||
! Packet ID | ! Packet ID | ||
| Line 608: | Line 480: | ||
! Notes | ! Notes | ||
|- | |- | ||
|rowspan="11"| | |rowspan="11"| 0x80–0x9f | ||
|colspan="3"| Sequence number | |colspan="3"| Sequence number | ||
| uint24le | | uint24le | ||
| Line 615: | Line 487: | ||
|rowspan="10"| Frames | |rowspan="10"| Frames | ||
|colspan="2"| Flags | |colspan="2"| Flags | ||
| | | Byte | ||
| Top 3 bits give the reliability type, fourth bit is 1 when the frame is fragmented and part of a compound. | | Top 3 bits give the reliability type, fourth bit is 1 when the frame is fragmented and part of a compound. | ||
|- | |- | ||
|colspan="2"| | |colspan="2"| Body bit length | ||
| | | Unsigned Short | ||
| Length of | | Length of this frame's body in bits. | ||
|- | |- | ||
|colspan="2"| Reliable frame index | |colspan="2"| Reliable frame index | ||
| Line 630: | Line 502: | ||
| Only if sequenced, used for discarding out-of-date packets | | Only if sequenced, used for discarding out-of-date packets | ||
|- | |- | ||
|rowspan="2"| Order<br>( | |rowspan="2"| Order<br>(if ordered or sequenced) | ||
| Ordered frame index | | Ordered frame index | ||
| uint24le | | uint24le | ||
| Line 636: | Line 508: | ||
|- | |- | ||
| Order channel | | Order channel | ||
| | | Byte | ||
| Maximum of 32 channels | | Maximum of 32 channels | ||
|- | |- | ||
|rowspan="3"| Fragment<br>(only if fragmented) | |rowspan="3"| Fragment<br>(only if fragmented) | ||
| Compound size | | Compound size | ||
| | | Unsigned Int | ||
| | | Number of fragments in the split message. | ||
|- | |- | ||
| Compound ID | | Compound ID | ||
| | | Unsigned Short | ||
| Identifies which compound this fragment is part of | | Identifies which compound this fragment is part of | ||
|- | |- | ||
| Index | | Index | ||
| | | Unsigned Int | ||
| | | Zero-based index of this fragment in the split message. | ||
|- | |- | ||
| Body | | Body | ||
| ceil(length/8) bytes | | ceil(length/8) bytes | ||
| | | | ||
|} | |} | ||
A frame-set header has bit {{cd|0x80}} set and ACK/NACK bits {{cd|0x60}} clear. The remaining bits are flags, so the header is not a fixed message ID. A frame set can contain multiple frames.<ref name="frames">[https://github.com/Sandertv/go-raknet/blob/master/packet.go go-raknet: Frame encoding]</ref> | |||
The reliability values transmitted in the frame header are as follows: | |||
The reliability | |||
{| class="wikitable" | {| class="wikitable" | ||
| Line 667: | Line 537: | ||
! style="font-weight: bold;" | Name | ! style="font-weight: bold;" | Name | ||
! style="text-align: center; font-weight: bold;" | Reliable | ! style="text-align: center; font-weight: bold;" | Reliable | ||
! style="text-align: center; font-weight: bold;" | Sequenced | |||
! style="text-align: center; font-weight: bold;" | Ordered | ! style="text-align: center; font-weight: bold;" | Ordered | ||
|- | |- | ||
| style="text-align: center;" | 0 | | style="text-align: center;" | 0 | ||
| Line 680: | Line 550: | ||
| style="text-align: center;" | | | style="text-align: center;" | | ||
| style="text-align: center;" | x | | style="text-align: center;" | x | ||
| style="text-align: center;" | | | style="text-align: center;" | | ||
|- | |- | ||
| style="text-align: center;" | 2 | | style="text-align: center;" | 2 | ||
| Line 691: | Line 561: | ||
| reliable ordered | | reliable ordered | ||
| style="text-align: center;" | x | | style="text-align: center;" | x | ||
| style="text-align: center;" | | |||
| style="text-align: center;" | x | | style="text-align: center;" | x | ||
|- | |- | ||
| style="text-align: center;" | 4 | | style="text-align: center;" | 4 | ||
| reliable sequenced | | reliable sequenced | ||
| style="text-align: center;" | x | | style="text-align: center;" | x | ||
| style="text-align: center;" | x | | style="text-align: center;" | x | ||
| Line 719: | Line 571: | ||
|} | |} | ||
Sequenced | The original RakNet API also defines receipt modes 5, 6, and 7. These are encoded as wire values 0, 2, and 3 respectively; receipt notification is handled locally.<ref>[https://github.com/facebookarchive/RakNet/blob/master/Source/ReliabilityLayer.cpp RakNet: Reliability layer]</ref> | ||
Sequenced delivery discards older packets when a newer packet has arrived. Ordered delivery preserves the order of reliable packets within a channel. | |||
=== Game Packet === | === Game Packet === | ||
This Bedrock-specific message carries a batch of game packets inside a RakNet frame. | |||
{| class="wikitable" | {| class="wikitable" | ||
! Packet ID | ! Packet ID | ||
| Line 731: | Line 588: | ||
| Body | | Body | ||
| bytes | | bytes | ||
| | | In [[Minecraft:Bedrock Edition]], the body contains a batch of game packets. Framing and compression are described in [[Minecraft:Bedrock Edition protocol#Packet format|Bedrock Edition protocol]]. | ||
|} | |} | ||
Packet definitions are listed at [[Minecraft:Bedrock Edition protocol/Packets]]. | |||
=== NACK === | === NACK === | ||
This packet reports [[Minecraft:wikipedia:User_Datagram_Protocol|datagrams]] that were not received so the sender can retransmit them when required. | |||
{| class="wikitable" | {| class="wikitable" | ||
! style="font-weight: bold;" | Packet ID | ! style="font-weight: bold;" | Packet ID | ||
| Line 744: | Line 604: | ||
| rowspan="5" | 0xa0 | | rowspan="5" | 0xa0 | ||
| colspan="3" | Record count | | colspan="3" | Record count | ||
| | | Unsigned Short | ||
| Number of records in the packet | | Number of records in the packet | ||
|- | |- | ||
| Line 755: | Line 615: | ||
| Sequence number | | Sequence number | ||
| uint24le | | uint24le | ||
| | | Datagram sequence number in this record. | ||
|- | |- | ||
| rowspan="2" | Range, if <code>is_single == false</code> | | rowspan="2" | Range, if <code>is_single == false</code> | ||
| Start Sequence number | | Start Sequence number | ||
| uint24le | | uint24le | ||
| | |First datagram sequence number in the inclusive range. | ||
|- | |- | ||
| End Sequence number | | End Sequence number | ||
| uint24le | | uint24le | ||
| | |Last datagram sequence number in the inclusive range. | ||
|} | |} | ||
A NACK | A NACK reports frame-set sequence numbers that were not received, prompting retransmission where required. | ||
=== ACK === | === ACK === | ||
This packet acknowledges [[Minecraft:wikipedia:User_Datagram_Protocol|datagrams]] received from the other peer. | |||
{| class="wikitable" | {| class="wikitable" | ||
! style="font-weight: bold;" | Packet ID | ! style="font-weight: bold;" | Packet ID | ||
| Line 777: | Line 640: | ||
| rowspan="5" | 0xc0 | | rowspan="5" | 0xc0 | ||
| colspan="3" | Record count | | colspan="3" | Record count | ||
| | | Unsigned Short | ||
| Number of records in the packet | | Number of records in the packet | ||
|- | |- | ||
| Line 788: | Line 651: | ||
| Sequence number | | Sequence number | ||
| uint24le | | uint24le | ||
| | | Datagram sequence number in this record. | ||
|- | |- | ||
| rowspan="2" | Range, if <code>is_single == false</code> | | rowspan="2" | Range, if <code>is_single == false</code> | ||
| Start Sequence number | | Start Sequence number | ||
| uint24le | | uint24le | ||
| | |First datagram sequence number in the inclusive range. | ||
|- | |- | ||
| End Sequence number | | End Sequence number | ||
| uint24le | | uint24le | ||
| | |Last datagram sequence number in the inclusive range. | ||
|} | |} | ||
An ACK | An ACK reports frame-set sequence numbers that were received. Both ACK and NACK packets can contain multiple records. | ||
== References == | == References == | ||
| Line 810: | Line 671: | ||
[[Category:Bedrock Edition]] | [[Category:Bedrock Edition]] | ||
Latest revision as of 11:10, 20 October 2026
RakNet is a networking library and protocol for multiplayer games. It runs over UDP and provides connection management, configurable reliability and ordering, sequencing, and fragmentation.
UDP does not guarantee delivery or ordering. RakNet supports different delivery modes, so applications can request reliability or ordering when needed.
The source code for RakNet is available in the archived source repository.
Use in Bedrock Edition
Minecraft:NetherNet became the default transport for Minecraft:Bedrock Dedicated Server in Minecraft:26.50.<ref>Template:Cite</ref> RakNet is deprecated in Minecraft:26.60, which removes client support for it.<ref>Template:Cite</ref>
Libraries
The following libraries implement RakNet. Supported features and protocol versions vary between implementations.
| Name | Description | Language | License |
|---|---|---|---|
| go-raknet | RakNet implementation written in Go. | Go | MIT |
| RakNet | Asynchronous RakNet implementation written in Rust. | Rust | Apache-2.0 |
| PieRakNet | RakNet implementation written in Python. | Python | GPL-3.0 |
| Cloudburst Network | Network components used by CloudburstMC projects. | Java | Apache-2.0 |
| rak-net | Python RakNet implementation originally developed for Podrum. | Python | GPL-2.0 |
| JRakNet | Java implementation of the RakNet protocol. | Java | MIT |
| netty-raknet | RakNet implementation for Netty. | Java | MIT |
| JRakLibPlus | RakNet server library based on RakLib and JRakLib. | Java | LGPL-3.0 |
| RakLib | Lightweight PHP RakNet server implementation. | PHP | GPL-3.0 |
| raknet | UDP networking library for Node.js that follows the RakNet protocol. | JavaScript | MIT |
| PyRakLib | Python port of RakLib that follows the RakNet protocol. | Python | GPL |
| rust-raknet | RakNet implementation written in Rust. | Rust | MIT |
| Baltica | Bedrock toolkit that includes a RakNet implementation. | TypeScript | See repository |
| RakNet.Py | RakNet implementation written in Python. | Python | GPL-2.0 |
| LavishMC RakNet | C++ fork of the original RakNet implementation. | C++ | BSD |
| RakNet (original) | Original C++ RakNet implementation. | C++ | BSD-2-Clause |
Data types
The types below describe the packet layouts on this page. Multi-byte integers are big-endian unless stated otherwise; 24-bit indices are little-endian. Address structures have their own byte order.<ref>RakNet: BitStream go-raknet: Frame encoding</ref>
| Type | Size | Description |
|---|---|---|
| Byte | 1 byte | Unsigned 8-bit value. |
| Boolean | 1 byte | Template:Cd is false; Template:Cd is true. |
| Short | 2 bytes | Signed 16-bit integer. |
| Unsigned Short | 2 bytes | Unsigned 16-bit integer. |
| Int | 4 bytes | Signed 32-bit integer. |
| Unsigned Int | 4 bytes | Unsigned 32-bit integer. |
| Long | 8 bytes | 64-bit integer. Whether it represents a signed value depends on the field. |
| uint24le | 3 bytes | Unsigned 24-bit little-endian integer, used for datagram sequence numbers and frame indices. |
| String | Variable | An unsigned 16-bit byte length followed by that many string bytes. |
| Magic | 16 bytes | The fixed Template:Cd value used in offline packets.<ref>RakNet: RakPeer.cpp</ref> |
| Address | 7 bytes (IPv4); 29 bytes (IPv6) |
Encodes the address family, address and port. IPv4 address bytes are inverted; the port is big-endian. IPv6 also includes address-family, flow-info and scope fields.<ref name="address-format">go-raknet: Address encoding</ref> |
Handshake sequence
The handshake begins with unconnected UDP packets and continues with connection-control messages carried inside RakNet frames.<ref>RakNet: RakPeer.cpp go-raknet: Connection messages</ref>
- C→S: Open Connection Request 1
- S→C: Open Connection Reply 1 (or Incompatible Protocol)
- C→S: Open Connection Request 2
- S→C: Open Connection Reply 2. The peers can now exchange framed connection-control messages.
- C→S: Connection Request
- S→C: Connection Request Accepted
- C→S: New Incoming Connection
After this exchange, the RakNet connection is established. Connection Request, Connection Request Accepted, and New Incoming Connection are themselves carried inside frames. In Minecraft:Bedrock Edition, game packets are carried in RakNet frames as described at Game Packet.
Packets
Offline packet IDs identify UDP datagrams; connected message IDs identify the payload inside a frame. The handshake tables below describe the layout with RakNet security disabled. Optional security handshakes and connection passwords are not included. Field details can vary by implementation.<ref>RakNet: Message identifiers go-raknet: Frame encoding</ref>
Unconnected Ping
The client sends this packet to discover a server. ID Template:Cd is a regular unconnected ping; Template:Cd asks for a response only when the server is accepting new connections. The server replies with Unconnected Pong.
| Packet ID | Field Name | Field Type |
|---|---|---|
| 0x01, 0x02 | Time | Long |
| Magic | Magic | |
| Client GUID | Long |
Unconnected Pong
The server sends this in response to an unconnected ping. It echoes the ping time and includes its GUID and a server ID string. In Minecraft:Bedrock Edition, that string contains server-list information in a semicolon-delimited format; its fields can vary by game version.
| Packet ID | Field Name | Field Type | Notes |
|---|---|---|---|
| 0x1c | Time | Long | |
| Server GUID | Long | ||
| Magic | Magic | ||
| Server ID String | String | Carries server-list information. |
Connected Ping
This packet measures latency on an established connection. It is commonly sent unreliably.
| Packet ID | Field Name | Field Type |
|---|---|---|
| 0x00 | Time | Long |
Connected Pong
The receiver replies with the original ping time and its own response time. It is commonly sent unreliably.
| Packet ID | Field Name | Field Type |
|---|---|---|
| 0x03 | Ping Time | Long |
| Pong Time | Long |
Open Connection Request 1
The first packet in the handshake sequence, sent by the client to the server.
| Packet ID | Field Name | Field Type | Notes |
|---|---|---|---|
| 0x05 | Magic | Magic | |
| Protocol version | Byte | RakNet protocol version used by the client; separate from the Bedrock game protocol version. | |
| Padding | Zero bytes | Zero padding used to probe the path MTU. |
The MTU is inferred from the datagram length, including IP and UDP overhead; it is not a numeric field in this request. The server replies with the selected MTU, or sends Incompatible Protocol if it does not support the client's RakNet protocol version.
Open Connection Reply 1
The second packet in the handshake sequence, sent by the server to the client.
| Packet ID | Field Name | Field Type | Notes |
|---|---|---|---|
| 0x06 | Magic | Magic | |
| Server GUID | Long | ||
| Use security | Boolean | False for the layout shown here. | |
| MTU | Unsigned Short | Selected MTU for the connection. |
Open Connection Request 2
The third packet in the handshake sequence, sent by the client to the server.
| Packet ID | Field Name | Field Type |
|---|---|---|
| 0x07 | Magic | Magic |
| Server Address | Address | |
| MTU | Unsigned Short | |
| Client GUID | Long |
Open Connection Reply 2
The fourth packet in the handshake sequence, sent by the server to the client.
| Packet ID | Field Name | Field Type | Notes |
|---|---|---|---|
| 0x08 | Magic | Magic | |
| Server GUID | Long | ||
| Client Address | Address | ||
| MTU | Unsigned Short | ||
| Encryption enabled | Boolean | False for the layout shown here. |
Connection Request
The client sends this framed message after Open Connection Reply 2 to continue the RakNet handshake.
| Packet ID | Field Name | Field Type |
|---|---|---|
| 0x09 | GUID | Long |
| Time | Long | |
| Use security | Boolean |
Connection Request Accepted
The server sends this packet to accept the client's connection request.
| Packet ID | Field Name | Field Type | Notes |
|---|---|---|---|
| 0x10 | Client address | Address | |
| System index | Unsigned Short | System index assigned by the server. | |
| Internal addresses | Address array | Internal server addresses; the count varies by implementation, commonly 10 or 20.<ref name="accepted-addresses">go-raknet: Connection Request Accepted</ref> | |
| Request time | Long | Timestamp from the corresponding Connection Request. | |
| Time | Long | Server acceptance time. |
New Incoming Connection
The client sends this packet to confirm that it received the server's acceptance.
| Packet ID | Field Name | Field Type | Notes |
|---|---|---|---|
| 0x13 | Server address | Address | |
| Internal addresses | Address array | Internal client addresses; the count varies by implementation, commonly 10 or 20.<ref>go-raknet: New Incoming Connection</ref> | |
| Ping time | Long | Server acceptance timestamp echoed by the client. | |
| Pong time | Long | Time at which the client sends this message. |
Disconnection Notification
This packet notifies the other peer that the sender is disconnecting.
| Packet ID | Field Name | Field Type | Notes |
|---|---|---|---|
| 0x15 | No payload | Signals that the sender is disconnecting. | |
Incompatible Protocol
The server sends this packet when it does not support the RakNet protocol version used by the client.
| Packet ID | Field Name | Field Type |
|---|---|---|
| 0x19 | Protocol | Byte |
| Magic | Magic | |
| Server GUID | Long |
Frame Set Packet
This packet carries one or more frames between connected peers.
| Packet ID | Field Name | Field Type | Notes | ||
|---|---|---|---|---|---|
| 0x80–0x9f | Sequence number | uint24le | Used for building ACK and NACK ranges | ||
| Frames | Flags | Byte | Top 3 bits give the reliability type, fourth bit is 1 when the frame is fragmented and part of a compound. | ||
| Body bit length | Unsigned Short | Length of this frame's body in bits. | |||
| Reliable frame index | uint24le | Only if reliable, used for detecting frame level duplication | |||
| Sequenced frame index | uint24le | Only if sequenced, used for discarding out-of-date packets | |||
| Order (if ordered or sequenced) |
Ordered frame index | uint24le | Tells the receiver the correct order in which to deliver frames to the application | ||
| Order channel | Byte | Maximum of 32 channels | |||
| Fragment (only if fragmented) |
Compound size | Unsigned Int | Number of fragments in the split message. | ||
| Compound ID | Unsigned Short | Identifies which compound this fragment is part of | |||
| Index | Unsigned Int | Zero-based index of this fragment in the split message. | |||
| Body | ceil(length/8) bytes | ||||
A frame-set header has bit Template:Cd set and ACK/NACK bits Template:Cd clear. The remaining bits are flags, so the header is not a fixed message ID. A frame set can contain multiple frames.<ref name="frames">go-raknet: Frame encoding</ref>
The reliability values transmitted in the frame header are as follows:
| ID | Name | Reliable | Sequenced | Ordered |
|---|---|---|---|---|
| 0 | unreliable | |||
| 1 | unreliable sequenced | x | ||
| 2 | reliable | x | ||
| 3 | reliable ordered | x | x | |
| 4 | reliable sequenced | x | x |
The original RakNet API also defines receipt modes 5, 6, and 7. These are encoded as wire values 0, 2, and 3 respectively; receipt notification is handled locally.<ref>RakNet: Reliability layer</ref>
Sequenced delivery discards older packets when a newer packet has arrived. Ordered delivery preserves the order of reliable packets within a channel.
Game Packet
This Bedrock-specific message carries a batch of game packets inside a RakNet frame.
| Packet ID | Field Name | Field Type | Notes |
|---|---|---|---|
| 0xfe | Body | bytes | In Minecraft:Bedrock Edition, the body contains a batch of game packets. Framing and compression are described in Bedrock Edition protocol. |
Packet definitions are listed at Minecraft:Bedrock Edition protocol/Packets.
NACK
This packet reports datagrams that were not received so the sender can retransmit them when required.
| Packet ID | Field Name | Field Type | Notes | ||
|---|---|---|---|---|---|
| 0xa0 | Record count | Unsigned Short | Number of records in the packet | ||
| Records | Is Single? | boolean | False for range, True for no range | ||
No Range, if is_single == true
|
Sequence number | uint24le | Datagram sequence number in this record. | ||
Range, if is_single == false
|
Start Sequence number | uint24le | First datagram sequence number in the inclusive range. | ||
| End Sequence number | uint24le | Last datagram sequence number in the inclusive range. | |||
A NACK reports frame-set sequence numbers that were not received, prompting retransmission where required.
ACK
This packet acknowledges datagrams received from the other peer.
| Packet ID | Field Name | Field Type | Notes | ||
|---|---|---|---|---|---|
| 0xc0 | Record count | Unsigned Short | Number of records in the packet | ||
| Records | Is Single? | boolean | False for range, True for no range | ||
No Range, if is_single == true
|
Sequence number | uint24le | Datagram sequence number in this record. | ||
Range, if is_single == false
|
Start Sequence number | uint24le | First datagram sequence number in the inclusive range. | ||
| End Sequence number | uint24le | Last datagram sequence number in the inclusive range. | |||
An ACK reports frame-set sequence numbers that were received. Both ACK and NACK packets can contain multiple records.