Facepunch.Steamworks Wiki

Creating A Socket Server

This will show you how to create a socket server, like the dedicated server in Rust.

There are a couple of ways to create your server .

A Server Class

You can override SocketManager to create your class, like this:

public class MyServer : SocketManager { public override void OnConnecting( Connection connection, ConnectionInfo data ) { base.OnConnecting(connection, data); connection.Accept(); Console.WriteLine( $"{data.Identity} is connecting" ); } public override void OnConnected( Connection connection, ConnectionInfo data ) { base.OnConnected(connection, data); Console.WriteLine( $"{data.Identity} has joined the game" ); } public override void OnDisconnected( Connection connection, ConnectionInfo data ) { base.OnDisconnected(connection, data); Console.WriteLine( $"{data.Identity} is out of here" ); } public override void OnMessage( Connection connection, NetIdentity identity, IntPtr data, int size, long messageNum, long recvTime, int channel ) { base.OnMessage(connection, identity, data, size, messageNum, recvTime, channel); Console.WriteLine( $"We got a message from {identity}!" ); // Send it right back connection.SendMessage( data, size, SendType.Reliable ); } }

Then you'd create/start your server like this

MyServer server = SteamNetworkingSockets.CreateNormalSocket<MyServer>( Data.NetAddress.AnyIp( 21893 ) );

An Interface

It might be simpler for you to create it using an interface. This is useful if you already have a class you want to act as the server, rather than building the whole thing around the network system.

public class MyServer : ISocketManager { public void OnConnecting( Connection connection, ConnectionInfo data ) { connection.Accept(); Console.WriteLine( $"{data.Identity} is connecting" ); } public void OnConnected( Connection connection, ConnectionInfo data ) { Console.WriteLine( $"{data.Identity} has joined the game" ); } public void OnDisconnected( Connection connection, ConnectionInfo data ) { Console.WriteLine( $"{data.Identity} is out of here" ); } public void OnMessage( Connection connection, NetIdentity identity, IntPtr data, int size, long messageNum, long recvTime, int channel ) { Console.WriteLine( $"We got a message from {identity}!" ); // Send it right back connection.SendMessage( data, size, SendType.Reliable ); } }

Then you'd start your server like this, where myServer is an instance of a class with the ISocketManager interface.

SocketManager manager = SteamNetworkingSockets.CreateNormalSocket( Data.NetAddress.AnyIp( 21893 ), myServer );

Which One?

It's up to you. Neither is better than the other, I just did it this way to give some flexibility.

In Rust I used the interface approach because our network system has to derive from a specific class. It was cleaner to do it this way.

If I was starting from scratch I'd probably do the class method.

Clients

You can get a list of clients via the SocketManager class.

// // Kick everyone // foreach ( var connection in Connected ) { connection.Close(); }

Client can connect with ConnectNormal or ConnectRelay and need to be stored with a ConnectionManager or a class that inherit from it :

MyConnectionManager hostConnection = SteamNetworkingSockets.ConnectRelay<MyConnectionManager>(hostSteamID);
The Connection type must match between client and server; Either use CreateNormalSocket with ConnectNormal, or CreateRelaySocket with ConnectRelay.

Message Format

Messages formats aren't defined. That's up to you to figure out yourself. We just send the raw data from one connection to another.

Where possible try to use the Connection.Send method which takes an IntPtr. If you're passing byte[] or string then you're probably creating garbage unless you know what you're doing.