The Steam networking API is a simple set of functions to let the game send data directly between two Steam users. To make connections from behind home NAT's, it uses the libjingle
NAT-punching library or, if no direct connection can be made, through the Steam relay servers.
The networking functions all live in ISteamNetworking
. It's connectionless, using the SteamID's of the users as the destination names. It's message-oriented (as opposed to steam-oriented), meaning you'll never receive fragments of messages you send, the underlying layer will always build it up into a complete message before sending it.
This API works best when used with Steam Matchmaking & Lobbies
, depending on the types of packets you could route everything through one player that is acting as the host (typically the lobby owner) or game server, or send everything out directly to each player.
For there are many great articles on various networking topics around the internet. A few recommendations from us:
See the Steamworks API Example Application (SpaceWar)
for an example of using this API.
To send a packet you must use ISteamNetworking::SendP2PPacket
Accepting packets from remote users
Before a real connection is established to a remote host, the game will get a chance to say whether or not a user is allowed to talk to them. When a remote user, that you haven't sent a packet to recently, tries to first send you a packet, your game will receive a callback P2PSessionRequest_t
. In response to this callback you should call ISteamNetworking::AcceptP2PSessionWithUser
to open the direct connection to the user.
Retrieval of data from the socket is done by polling. You'll want to check frequently; otherwise you'll be adding latency to the connection.
The typical usage is to call ISteamNetworking::IsP2PPacketAvailable
in a loop until it returns false. It returns the size of the message, which you can then use to allocate a buffer to pass into ISteamNetworking::ReadP2PPacket
If you know the maximum size of a packet, you can just pass that fixed size buffer into ISteamNetworking::ReadP2PPacket
directly, and then call it in a loop instead, as it will return false when there are no more packets available on that channel.
will try for up to 20 seconds to establish a connection to the remote user and deliver the packet. Your first sends may be delayed by that long. If there is an error establishing the connection, a P2PSessionConnectFail_t
will be posted. Further sends to a user will continue to try and establish the connection (potentially resulting in more P2PSessionConnectFail_t
To get information about the underlying connection state, call:ISteamNetworking::GetP2PSessionState
This returns details like whether or not there is an active connection; number of bytes queued on the connection; the last error code, if any; whether or not a relay server is being used; and the IP and Port of the remote user, if known.
Underlying the p2p connection can be a UDP, TCP, or relay-server connection to the remote user. This is established on first send, and will be re-used if it already exists.
A connection that is left unused for several minutes (no sends or receives) will be automatically cleaned up, But it's recommended that you hint to the API an early cleanup by calling: ISteamNetworking::CloseP2PSessionWithUser
This function immediately cleans up any underlying connection to the remote user. You'll want to use this if you're making a lot of connections to other users in a short time.