KCP-Based Real-Time Game Communication Case Study
In real-time online games, the latency from when a player's input is sent to the server until the result returns is crucial. While TCP guarantees reliability and transmission order, while waiting for lost data, the delivery of subsequently arrived data may also be delayed. Since UDP does not guarantee transmission order or arrival, a supplementary mechanism is required to handle messages that need reliability.
KCP is a protocol that provides retransmission and order control, primarily running on top of UDP. This article examines the principles by which KCP reduces latency and organizes the connection/authentication process and message structure based on a game communication case study. The authentication procedure and application message format may vary depending on the implementation.
How Does KCP Reduce Latency?
KCP implements reliable transmission using an ARQ method that utilizes acknowledgment and retransmission. By adjusting the retransmission policy and update interval, the waiting time after a loss can be reduced, though bandwidth and CPU usage may increase depending on the configuration.
Actual performance varies depending on network conditions and settings.
- Selective Retransmission: Selectively retransmits lost data based on acknowledgment information. Since TCP also supports selective retransmission using SACK, this cannot be considered a feature exclusive to KCP.
- Retransmission Timeout Adjustment: In fast mode, when losses repeat, it reduces the increment of retransmission wait time to accelerate recovery.
- Fast Retransmission: The sender infers the loss of a preceding packet by observing the arrival of ACKs for subsequent packets. If set conditions are met, it retransmits before the timeout.
- Short Update Interval: By reducing the update and transmission intervals, it minimizes the wait until ACKs and retransmitted data are sent. The actual transmission timing is also affected by the application's call cycle.
Since KCP also delivers data in order, the phenomenon where subsequent data waits if preceding data is lost still remains. The core is not to eliminate this wait, but to recover lost data more quickly.
Connection and Authentication Process
Before communicating with the game server, account authentication and selection of the server to connect to are required. The following is a simplified example of the flow in which a token received via web authentication is verified by the game server.
In this example, the web server authenticates the account, and the game server verifies the token to start the game session. Distinguishing the roles of these two stages makes it easier to understand the communication flow after login.
KCP itself does not have encryption or user authentication features. If security is required, a separate security layer must be configured. Since Protobuf is also a format for serializing data, simply representing keys or tokens with Protobuf does not guarantee secure delivery.
KCP Headers and Application Messages
A KCP segment consists of a 24-byte header and a data area. From conv to len in the table below are the KCP headers, and PackLen, MsgType, CmdId, etc., inside the data area are the application message formats covered in this case. This internal format is not a common specification of KCP.
The table represents one cell as 1 byte. Since large application messages can be split into multiple KCP segments, the internal table should be read as an example showing the structure of the reassembled message.
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ||||||||||||||||||||||||||||||||
| conv | cmd | frg | wnd | ||||||||||||||||||||||||||||||||||||
| ts | sn | ||||||||||||||||||||||||||||||||||||||
| una | len | ||||||||||||||||||||||||||||||||||||||
Data: Application Message Example
|
|||||||||||||||||||||||||||||||||||||||
In the KCP header, conv is the conversation identifier, cmd is the command type, frg is the fragment information, and wnd is the receive window size. ts represents the timestamp, sn the segment sequence number, una the next expected sequence number, and len the length of the data area.
The fields of the application message can be interpreted as follows. The calculation range for length and checksum should be verified against the rules of each implementation.
PackLen: Field indicating the message length.MsgType: Message type and flag information.seqNo: Sequence number of the application message.rpcId: Identifier connecting remote procedure call requests and responses.CmdId: Identifier indicating the message type to interpret the payload.crc32: Checksum for error detection. It does not replace cryptographic authentication.Payload: Serialized message data. If encryption is applied, it is decrypted and then interpreted.
Interpreting Payloads with Protobuf
The payload in this case contains data serialized using Protocol Buffers (Protobuf). Protobuf is a format that represents structured data in binary, using numbers instead of field names. While it can express game messages concisely, size and processing performance depend on the data structure and implementation.
First, define the message structure in a .proto file, and generate code matching the language to be used via protoc. The sender serializes data using this code, and the receiver deserializes it using the same message definition.
For example, you can define a message containing two strings as follows.
Suppose the application defines the correspondence between CmdId and message types as follows. This number is not automatically assigned by Protobuf, but is a rule defined by the application.
Serializing a message where message is Hello World! and name is AZA.GG yields the following byte sequence. The payload below is the data before encryption.
Preceding each string are a tag containing the field number and data type, and the byte length of the string. 0a and 12 are the tags for fields 1 and 2, respectively, and 0c and 06 represent the string lengths 12 and 6.
The receiver verifies that CmdId is 11 and interprets the payload as HelloWorld. Thus, KCP handles transmission and retransmission, the application header handles message distinction, and Protobuf handles data representation.