Документація Steamworks
Ретрансляція датаграм Steam
Ретрансляція датаграм Steam (Steam Datagram Relay, SDR) — це приватна віртуальна ігрова мережа Valve. За допомогою нашого API ви можете не лише перенести свій ігровий трафік за допомогою мережевої магістралі ігрового вмісту Valve, ви також можете отримати доступ до нашої мережі ретрансляцій. Ретрансляція трафіку захищає ваші сервери та гравців від DoS-атак, оскільки IP-адреси ніколи не розкриваються. Увесь отримуваний вами трафік є автентифікований, зашифрований і має ліміт на частоту. Для особливо великої кількості гравців ми можемо знайти швидший маршрут через нашу мережу, що покращує час пінґу в гравців.

Цю ретрансляційну мережу можна використовувати і для однорангового трафіку, і для виділених серверів.

Загальні вимоги та поради щодо перенесення наявного коду мережі

Нижче наведено кілька важливих моментів стосовно однорангового підключення та підключення до виділеного сервера.

По-перше, усі місця, де вузли мережі визначаються загальнодоступною IP-адресою (майже завжди у випадку ігрових серверів), потрібно змінити — для них має використовуватися інший ідентифікатор. Ось що варто взяти до уваги:
  • Для клієнтів та ігрових серверів, які здійснюють вхід до акаунта Steam, зазвичай варто використовувати SteamID.
  • Якщо ваш ігровий сервер не здійснює вхід до акаунта Steam і використовується цикл автентифікації на основі квитка, тоді можна використовувати будь-який інший зрозумілий ідентифікатор. Див. SteamNetworkingIdentity.
  • Існує поширене припущення стосовно деяких кодових баз: вузли мережі та ігрові сервери визначаються за допомогою IPv4-адреси. Зміна цього припущення потребує певної роботи. Дійсно, API Steamworks ISteamMatchmaking і ISteamMatchmakingServers мають цю властивість, як і деякі з наших ігор (наприклад, Team Fortress 2). У такому випадку можна використовувати систему Steamworks під назвою «Хибна IP-адреса» (Fake IP). FakeIP — це IP-адреса, що «схожа» на правильну IPv4-адресу для більшості використань, але вона має зарезервований адресний простір, що не використовується в Інтернеті. Призначивши FakeIP серверу, на нього все ще можна посилатися за допомогою IPv4-адреси — тоді майже все «просто працюватиме». Системи ISteamNetworkingSockets і ISteamMatchmakingServers розпізнають ці особливі IP-адреси та здійснюють необхідну дію. Вони не підтримують маршрутизацію й не підходять для загального використання в Інтернеті, адже ви не можете перевірити з ними зв’язок. Див. ISteamNetworkingSockets::BeginAsyncRequestFakeIP для докладнішої інформації.

По-друге, вам потрібно змінити код сокета нижнього рівня, щоби скористатися API Steamworks для можливостей підключення.
  • Найкраще використовувати зосереджений на підключенні інтерфейс API ISteamNetworkingSockets, який повертає HSteamNetConnection.
    Зверніть увагу, що ці API також підтримують просте перенесення UDP-зв’язку, що дуже корисно для тестування. Також існує версія з відкритим кодом.
  • Деякі бази кодів написані більше в стилі UDP-зв’язку, тобто пакети будь-коли можна надіслати на будь-який віддалений сервер, і не всі повідомлення відправляються на встановлене «підключення». У таких випадках вам стануть у пригоді дві функції Steamworks:
    • Використовуйте ISteamNetworkingMessages, щоби спілкуватися з вузлами, визначеними за допомогою типу SteamNetworkingIdentity, як-от SteamID.
    • Використовуйте ISteamNetworkingFakeUDPPort, щоби спілкуватися з вузлами, визначеними за допомогою FakeIP.

Requirements for using SDR on other platforms and stores

Мережевий API та рішення DDoS для міжплатформної гри не є корисними, якщо послуга працює лише на одній платформі. У більшості випадків ваші гравці з інших платформ і крамниць можуть отримати доступ до мережі ретранслятора, якщо ваша гра відповідає певним базовим умовам:
  • Версія гри має збігатися з версією в Steam.
  • Ви погоджуєтеся на вимогу оновлювати гру в розумних часових межах (до прикладу, раз у кілька місяців), якщо нам потрібно буде надіслати виправлення вад чи оновлення систем безпеки.
  • Ви повинні розуміти, що ми не можемо обіцяти, що ця служба завжди буде доступною для гравців за межами Steam. Якщо раптом, що малоймовірно, нам потрібно буде знизити версію служби, ми зробимо все від нас можливе, щоби ваші гравці нічого не відчули. Почнемо з того, що ви матимете час для планування переходу. SDK має вбудовані механізми, які дозволяють нам наказати клієнту використовувати прямий UDP-зв’язок або спробувати перфорацію NAT, але вам також варто порозмірковувати над цією можливістю.
  • Ви повинні мати якусь службу пошуку матчів (SDR називає її «ігровим координатором»), яка може видавати облікові дані автентифікації. Для цього ми маємо окремий SDK. Див. нижче.

Будь ласка, зв’яжіться з нами для отримання відповідних SDK та обговорення умов. We're still working through details of how to distribute this code, and at this time we might not be able to make cross-platform support available to all partners and all games.

See below for more technical information on implementing SDR on other platforms and stores.

If you don't meet the criteria above, feel free to use the opensource version of the API for whatever you want. Note that the opensource code does not support accessing the relay network.

Ігри з одноранговим підключенням

Щоб отримати переваги SDR для однорангового трафіку в Steam, треба лише використовувати такі API як ISteamNetworkingSockets::CreateListenSocketP2P та ISteamNetworkingSockets::ConnectP2P. Про решту подбає Steam. For other platforms and stores, read more about additional technical requirements below.

Виділені сервери у відомих дата-центрах

Однорангові API чудово працюють, навіть якщо один із «пірів» є виділеним сервером! Але є одна умова: якщо ваш виділений сервер не розташовано поблизу одного з дата-центрів, з яких ми здійснюємо ретрансляції, найліпший ретрансльований маршрут може бути повільнішим за простий IP-маршрут, тож щонайменше кілька користувачів отримають доволі велику затримку.

For the optimal dedicated server experience, the server should be run in a known data center that is part of the SDR network. We make sure that relays are running nearby and the relayed route is never too much slower than the default IP route. Servers running in these known data centers connect using a special API. This use case is referred to in the SDK as "Hosted Dedicated Server". Note that this doesn't necessarily mean that Valve is hosting the servers or the relays -- it could be a third party data center that we have established a relationship with, and is known to the Steam Datagram Relay system.

If you are running game servers in a major hosting provider and are interested in using SDR, please get in touch with us. We'll try to work with your hosting company to run relays in the data center. That's the ideal situation, but even if this is not possible we may be able to add the data center to our network configuration system and just use Valve relays that are nearby.

If you are a dedicated server hosting company and want to join our network so that your customers can take advantage of SDR, please get in touch with us! We have not yet deployed relays in any third party hosting companies, however we are interested in doing this.

Простий процес підключення до виділеного сервера без ігрового координатора

Якщо ви не маєте власної служби входу/пошуку матчів, яка пов’язує гравців із серверами (ми іноді називаємо її «ігровим координатором»), або просто не хочете нічого ускладнювати, то можете підключитися до відомого дата-центру за допомогою ISteamNetworkingSockets::CreateListenSocketP2P та ISteamNetworkingSockets::ConnectP2P. У такому разі підключення починається з боку клієнта, як і у звичайному одноранговому підключенні. Повідомлення Rendezvous надсилаються через Steam, тож якщо гравець або сервер утратять з’єднання зі Steam, підключення не вдасться встановити. Окрім того, Steam не обмежує спробу гравця підключитися, а лише перевіряє, чи увійшов гравець до акаунта Steam і чи володіє він відповідною грою.

Процес підключення до сервера на основі квитка

Якщо ви маєте власний ігровий координатор, рекомендуємо використовувати процес підключення на основі квитка. Зазвичай це трохи більше роботи, ніж звичайне однорангове підключення, але він має важливі переваги:
  • Ви видаєте квитки лише тим гравцям, яким дозволено спробувати підключитися, тож небажані спроби навіть не дійдуть до сервера.
  • Після отримання квитка гравець зможе підключитися до сервера, навіть якщо він втратить зв’язок зі Steam, сервер втратить зв’язок зі Steam, комп’ютер гравця аварійно завершить роботу й перезавантажиться тощо. Повторне підключення до ігрового сервера попри поширені проблеми особливо важливе для ігор, що карають гравців за вихід із гри.

A ticket-based connection to a dedicated server over SDR works like this:
  • Коли ваш ігровий сервер підключається до ігрового координатора, він надсилає свій SteamDatagramHostedAddress — непрозорий BLOB-об’єкт, що містить інформацію про фізичний маршрут (див. ISteamNetworkingSockets::GetHostedDedicatedServerAddress). Також майте на увазі, що ми маємо деякі інструменти, які можна використовувати для авторизованого входу до свого ігрового координатора.
  • Сервер починає приймати ретрансльований трафік за допомогою ISteamNetworkingSockets::CreateHostedDedicatedServerListenSocket.
  • На якомусь етапі ваш клієнт має перейти до пошуку матчів або підключитися до сервера.
  • Клієнт може використати методи інтерфейсу ISteamNetworkingUtils для отримання часу пінґу до дата-центрів і перевірки якості підключення. Можливо, ви захочете, щоби клієнт надіслав цю інформацію до вашого ігрового координатора, щоби краще розподілити гравців між дата-центрами.
  • Коли ваш ігровий координатор готовий авторизувати клієнт для підключення до сервера, він генерує SteamDatagramRelayAuthTicket й підписує його вашим секретним ключем. Цей квиток авторизує відповідного клієнта для певного ігрового сервера на обмежений період часу. Він також містить зашифровану інформацію про маршрут. Ігровий координатор надсилає квиток до клієнта.
  • Клієнт кешує квиток у локальному кеші (див. ISteamNetworkingSockets::ReceivedRelayAuthTicket для отримання докладнішої інформації, зокрема про те, чому корисно додатково ускладнювати кешування).
  • Клієнт використовує ISteamNetworkingSockets::ConnectToHostedDedicatedServer для підключення до сервера (див. ISteamNetworkingSockets для подальших подробиць стосовно надсилання й отримання повідомлень).

At this time, the ticket-based authentication is not available in combination with the FakeIP system.

SDK ігрового координатора

«Ігровий координатор» — це термін, яким ми позначаємо ваші сервіси виділених серверів та пошуку матчів. Існує невеликий окремий SDK, який ви можете використовувати зі своїм ігровим координатором для:
  • Видавання квитків, щоби надати клієнтам доступ до ігрових серверів за ретрансляцією датаграм Steam.
  • Парсування рядків PingLocation_t та обрахунку часу пінґу між цими об’єктами.
  • Видавання сертифікатів ідентичності гравцям на інших платформах та в інших крамницях.
  • Отримання переваг деяких інших розширених функцій.

The SDK is available here

Автентифікація за допомогою SDK ігрового координатора

Ретрансляція датаграм Steam використовує два механізми автентифікації:

  • Квитки обслуговуваних серверів видаються вашим ігровим координатором та авторизують конкретного клієнта для підключення до виділеного сервера на певний час. Квитки ретрансляції використовуються лише для виділених серверів (див. SteamDatagramRelayAuthTicket).
  • Сертифікати використовуються традиційним чином для автентифікації та обміну ключами DH для створення зашифрованого каналу. Сертифікати є наскрізною концепцією, яку можна використовувати в усіх формах комунікацій SteamNetworkingSockets, включно з прямим підключенням через протокол користувацьких датаграм чи одноранговим підключенням (див. SteamDatagram_CreateCert в SDK ігрового координатора та ISteamNetworkingSockets::GetCertificateRequest).

We use a proprietary public key infrastructure (PKI) to authenticate clients and servers. Players are issued individual, short-term certificates, tied to their specific player identity. Steam takes care of this. For gameservers, we typically use longer term certificates that authorize an entire data center for a particular AppID. You will issue those certificates.

Before you can issue tickets and certificates, you'll need to generate a keypair and send us your public key. We will publish a certificate signed by our master CA key that marks your key as trusted for your app(s). Then, offline you will generate a certificate for each data center where you want to run servers, using our certificate tool, and sign it with your private key. You'll distribute those certificates to your gameservers over a secure channel, passing it to your server in the environment (see below).

You'll also use your key to generate tickets, each time a player connects to a gameserver.

Keep your CA private key and the private keys of your certificates safe! If your key leaks and needs to be revoked and replaced, it could lead to a disruption.

Implementing SDR on other platforms and stores


Your clients on other platforms and stores will not sign into Steam, and so you will need to provide a few services for those players that Steam provides for Steam players.

Game coordinator initialization

  • Your matchmaking service (referred to as the "game coordinator") will need to link with the game coordinator SDK. The header file steamdatagram_gamecoordinator.h has more details. The game coordinator SDK uses a plain C API, so it should be relatively easy to integrate with other languages.
  • Download the network config at initialization time, and check for updates approximately once an hour. (See SteamDatagram_GameCoordinator_GetNetworkConfigURL and SteamDatagram_GameCoordinator_SetNetworkConfig.) The network configuration is a small JSON file, at the time of this writing, about 26K (9K compressed). This URL has very high availability, however if you wish to handle the possibility of failure, you can use a recently downloaded version.
  • You'll need a keypair authenticated for your game. Send us the public key, and initialize the game coordinator SDK with your private key. (See SteamDatagram_SetPrivateKey_Ed25519 for more information.)

Client signon

  • The client will call ISteamNetworkingSockets::GetCertificateRequest to get a blob and send it along with the signon request message to your game coordinator.
  • When the game coordinator receives the signon request, generate a certificate for the client using SteamDatagram_CreateCert.
  • Send the generated certificate back to the client in the logon response. The client should install their certificate using ISteamNetworkingSockets::SetCertificate
  • It is highly recommended that you also distribute the network configuration to clients at this time as well. The client will apply the network configuration using SteamDatagram_SetNetworkConfig.

Certificates have an expiry, and we recommend that you use an expiry of 48-hours. If clients might be connected for longer than 48 hours, then you will need to periodically renew the certificate. It is acceptable to apply a new certificate at any time, and so if you want to issue certificates more often, for example at the start of every match, that is OK.

Every client must have a unique identity. If possible, use the platform-specific identities. (For Steam clients, this is a requirement.) However, if this is not possible, you can use a "generic string" identity that is meaningful to your matchmaker. See SteamNetworkingIdentity.

Peer-to-peer games

P2P connections require a "signaling" service. This is a low-bandwidth, non-latency-sensitive, best-effort-delivery channel capable of forwarding occasional rendezvous messages used to negotiate routing. This requires clients to have a persistent connection to your matchmaking service, such that you can push messages to them, such as a websocket or TCP connection. If clients only talk to your game coordinator using a request/response pattern, for example through http, that won't work. You only need to provide "best effort" delivery, meaning that the library is tolerant of messages dropping or being delivered multiple times.

  • To initiate a connection, use ISteamNetworkingSockets::ConnectP2PCustomSignaling. You will need to implement a subclass of ISteamNetworkingConnectionSignaling, and when SendSignal is called, the client should send the message to your backend, and your backend should make its best effort to deliver the message to the peer. When a connection is first created, a initial exchange 4-10 messages is typical. Thereafter, you might be called to deliver a signal for an established connection if routing conditions change.
  • When a client receives a signal, call ISteamNetworkingSockets::ReceivedP2PCustomSignal. The library will decode the message. If it is concerning an existing connection, the signal will be processed internally. If the signal is for a new connection, ISteamNetworkingSignalingRecvContext::OnConnectRequest will be called.

See steamnetworkingcustomsignaling.h for more details.

Running servers in known data centers

This section documents some technical details involved in running dedicated servers in known data centers.

Environment variables

The dedicated server gets its configuration from environment variables. Note that in Valve data centers, all of these values will be set automatically for you.
  • SDR_LISTEN_PORT: The UDP port where your server will receive traffic from relays. The dedicated server only uses a single socket. (But you can have more than one logical "listen socket" by using "virtual ports". See ISteamNetworkingSockets::CreateHostedDedicatedServerListenSocket.) In our data centers, we typically use the 30xxx range.
  • SDR_IP: Your server must have a public IP that can receive "unsolicited" traffic from relays. If the server only has one interface with a public IP, then this will be used. Otherwise, you will need to tell the gameserver what IP to use. The SDR socket will be bound to INADDR_ANY, but this information is needed to fill out the server's SteamDatagramHostedAddress. Note in particular that this will usually need to be set in dev environments, where your server is behind a corporate firewall. (See below.) You can also specify a port, if the public port differs from SDR_LISTEN_PORT.
  • SDR_POPID: The 3- or 4-letter alphanumeric code (SteamNetworkingPOPID) of the data center, in production. In development environment, leave this blank.
  • SDR_PRIVATE_KEY: The private key from your certificate. It's an OpenSSH PEM block that begins with "-----BEGIN OPENSSH PRIVATE KEY-----".
  • SDR_CERT: Your signed certificate. It's a proprietary format PEM-like block that begins with "-----BEGIN STEAMDATAGRAM CERT-----".
  • SDR_NETWORK_CONFIG: Full path to a local, recent copy of the SDR network configuration file for your app. If this variable is not set, then to obtain the network configuration the server will fetch the copy using HTTP at boot time. For optimal performance you can periodically (e.g. once an hour) download the latest configuration and save it locally, so that a network hiccup doesn't cause any disruption. This is how Valve servers are configured.

Running in a dev environment

Because ISteamNetworkingSockets supports plain UDP connectivity, it's usually best to start by getting your code working through this interface over UDP, without worrying about relays.

We suggest that your server code use the presence of the SDR_LISTEN_PORT environment variable to decide whether your server should listen for SDR. You can use ISteamNetworkingSockets::GetHostedDedicatedServerPort to fetch the value.

In development, you will leave SDR_POPID blank. When SDR_LISTEN_PORT and SDR_POPID is blank, the POPID is set to the special 3-character code "dev".

In general, authentication is disabled for servers in the "dev" environment. (Clients and relays will both allow connections to "dev" servers without a signed cert, as long as they have a signed ticket.) You will need another mechanism to authenticate with your game coordinator. And your game coordinator needs to be careful when it issues tickets to any servers claiming to be in "dev"!

Your server needs to be able to receive unsolicited public traffic, which means that if it doesn't have a public IP, you'll need to setup a port forward in your firewall. And you'll probably need to set SDR_IP with the proper public IP (and port, if it differs from SDR_LISTEN_PORT).