Networking fixes

This commit is contained in:
Garry Newman 2020-02-22 11:17:12 +00:00
parent 43f4791b97
commit ba5c143dee
10 changed files with 300 additions and 254 deletions

View File

@ -99,6 +99,8 @@
<Compile Include="FriendsTest.cs" /> <Compile Include="FriendsTest.cs" />
<Compile Include="InputTest.cs" /> <Compile Include="InputTest.cs" />
<Compile Include="NetworkingSockets.cs" /> <Compile Include="NetworkingSockets.cs" />
<Compile Include="NetworkingSocketsTest.TestConnectionInterface.cs" />
<Compile Include="NetworkingSocketsTest.TestSocketInterface.cs" />
<Compile Include="SteamMatchmakingTest.cs" /> <Compile Include="SteamMatchmakingTest.cs" />
<Compile Include="RemoteStorageTest.cs" /> <Compile Include="RemoteStorageTest.cs" />
<Compile Include="InventoryTest.cs" /> <Compile Include="InventoryTest.cs" />

View File

@ -99,6 +99,8 @@
<Compile Include="FriendsTest.cs" /> <Compile Include="FriendsTest.cs" />
<Compile Include="InputTest.cs" /> <Compile Include="InputTest.cs" />
<Compile Include="NetworkingSockets.cs" /> <Compile Include="NetworkingSockets.cs" />
<Compile Include="NetworkingSocketsTest.TestConnectionInterface.cs" />
<Compile Include="NetworkingSocketsTest.TestSocketInterface.cs" />
<Compile Include="SteamMatchmakingTest.cs" /> <Compile Include="SteamMatchmakingTest.cs" />
<Compile Include="RemoteStorageTest.cs" /> <Compile Include="RemoteStorageTest.cs" />
<Compile Include="InventoryTest.cs" /> <Compile Include="InventoryTest.cs" />

View File

@ -12,7 +12,7 @@ namespace Steamworks
[TestClass] [TestClass]
[DeploymentItem( "steam_api64.dll" )] [DeploymentItem( "steam_api64.dll" )]
[DeploymentItem( "steam_api.dll" )] [DeploymentItem( "steam_api.dll" )]
public class NetworkingSocketsTest public partial class NetworkingSocketsTest
{ {
[TestMethod] [TestMethod]
@ -46,16 +46,18 @@ public async Task RelayEndtoEnd()
{ {
SteamNetworkingUtils.InitRelayNetworkAccess(); SteamNetworkingUtils.InitRelayNetworkAccess();
// For some reason giving steam a couple of seconds here
// seems to prevent it returning null connections from ConnectNormal
await Task.Delay( 2000 );
Console.WriteLine( $"----- Creating Socket Relay Socket.." ); Console.WriteLine( $"----- Creating Socket Relay Socket.." );
var socket = SteamNetworkingSockets.CreateRelaySocket<TestSocketInterface>( 7788 ); var socket = SteamNetworkingSockets.CreateRelaySocket<TestSocketInterface>( 6 );
var server = socket.RunAsync(); var server = socket.RunAsync();
Console.WriteLine( $"----- Created Relay Socket: {(uint)socket.Socket}" ); await Task.Delay( 1000 );
await Task.Delay( 5000 );
Console.WriteLine( $"----- Connecting To Socket via SteamId ({SteamClient.SteamId})" ); Console.WriteLine( $"----- Connecting To Socket via SteamId ({SteamClient.SteamId})" );
var connection = SteamNetworkingSockets.ConnectRelay<TestConnectionInterface>( SteamClient.SteamId, 7788 ); var connection = SteamNetworkingSockets.ConnectRelay<TestConnectionInterface>( SteamClient.SteamId, 6 );
var client = connection.RunAsync(); var client = connection.RunAsync();
await Task.WhenAll( server, client ); await Task.WhenAll( server, client );
@ -64,231 +66,26 @@ public async Task RelayEndtoEnd()
[TestMethod] [TestMethod]
public async Task NormalEndtoEnd() public async Task NormalEndtoEnd()
{ {
// For some reason giving steam a couple of seconds here
// seems to prevent it returning null connections from ConnectNormal
await Task.Delay( 2000 );
//
// Start the server
//
Console.WriteLine( "CreateNormalSocket" );
var socket = SteamNetworkingSockets.CreateNormalSocket<TestSocketInterface>( NetAddress.AnyIp( 12445 ) ); var socket = SteamNetworkingSockets.CreateNormalSocket<TestSocketInterface>( NetAddress.AnyIp( 12445 ) );
var server = socket.RunAsync(); var server = socket.RunAsync();
await Task.Delay( 5000 ); //
// Start the client
//
Console.WriteLine( "ConnectNormal" );
var connection = SteamNetworkingSockets.ConnectNormal<TestConnectionInterface>( NetAddress.From( System.Net.IPAddress.Parse( "127.0.0.1" ), 12445 ) ); var connection = SteamNetworkingSockets.ConnectNormal<TestConnectionInterface>( NetAddress.From( System.Net.IPAddress.Parse( "127.0.0.1" ), 12445 ) );
var client = connection.RunAsync(); var client = connection.RunAsync();
await Task.WhenAll( server, client ); await Task.WhenAll( server, client );
} }
private class TestConnectionInterface : ConnectionInterface
{
public override void OnConnectionChanged( ConnectionInfo data )
{
Console.WriteLine( $"[Connection][{Connection}] [{data.State}]" );
base.OnConnectionChanged( data );
}
public override void OnConnecting( ConnectionInfo data )
{
Console.WriteLine( $" - OnConnecting" );
base.OnConnecting( data );
}
/// <summary>
/// Client is connected. They move from connecting to Connections
/// </summary>
public override void OnConnected( ConnectionInfo data )
{
Console.WriteLine( $" - OnConnected" );
base.OnConnected( data );
}
/// <summary>
/// The connection has been closed remotely or disconnected locally. Check data.State for details.
/// </summary>
public override void OnDisconnected( ConnectionInfo data )
{
Console.WriteLine( $" - OnDisconnected" );
base.OnDisconnected( data );
}
internal async Task RunAsync()
{
Console.WriteLine( "[Connection] RunAsync" );
var sw = System.Diagnostics.Stopwatch.StartNew();
while ( Connecting )
{
await Task.Delay( 10 );
if ( sw.Elapsed.TotalSeconds > 30 )
break;
}
if ( !Connected )
{
Console.WriteLine( "[Connection] Couldn't connect!" );
Console.WriteLine( Connection.DetailedStatus() );
return;
}
Console.WriteLine( "[Connection] Hey We're Connected!" );
sw = System.Diagnostics.Stopwatch.StartNew();
while ( Connected )
{
Receive();
await Task.Delay( 100 );
if ( sw.Elapsed.TotalSeconds > 10 )
{
Assert.Fail( "Client Took Too Long" );
break;
}
}
}
public override unsafe void OnMessage( IntPtr data, int size, long messageNum, long recvTime, int channel )
{
// We're only sending strings, so it's fine to read this like this
var str = UTF8Encoding.UTF8.GetString( (byte*) data, size );
Console.WriteLine( $"[Connection][{messageNum}][{recvTime}][{channel}] \"{str}\"" );
if ( str.Contains( "Hello" ) )
{
Connection.SendMessage( "Hello, How are you!?" );
Connection.SendMessage( "How do you like 20 messages in a row?" );
for ( int i=0; i<20; i++ )
{
Connection.SendMessage( $"BLAMMO!" );
}
}
if ( str.Contains( "status" ))
{
Console.WriteLine( Connection.DetailedStatus() );
}
if ( str.Contains( "how about yourself" ) )
{
Connection.SendMessage( "I'm great, but I have to go now, bye." );
}
if ( str.Contains( "hater" ) )
{
Close();
}
}
}
private class TestSocketInterface : SocketInterface
{
public bool HasFinished = false;
public override void OnConnectionChanged( Connection connection, ConnectionInfo data )
{
Console.WriteLine( $"[Socket{Socket}][{connection}] [{data.State}]" );
base.OnConnectionChanged( connection, data );
}
public override void OnConnecting( Connection connection, ConnectionInfo data )
{
Console.WriteLine( $" - OnConnecting" );
base.OnConnecting( connection, data );
}
/// <summary>
/// Client is connected. They move from connecting to Connections
/// </summary>
public override void OnConnected( Connection connection, ConnectionInfo data )
{
Console.WriteLine( $" - OnConnected" );
base.OnConnected( connection, data );
}
/// <summary>
/// The connection has been closed remotely or disconnected locally. Check data.State for details.
/// </summary>
public override void OnDisconnected( Connection connection, ConnectionInfo data )
{
Console.WriteLine( $" - OnDisconnected" );
base.OnDisconnected( connection, data );
}
internal async Task RunAsync()
{
var sw = System.Diagnostics.Stopwatch.StartNew();
while ( Connected.Count == 0 )
{
await Task.Delay( 10 );
if ( sw.Elapsed.TotalSeconds > 2 )
{
Assert.Fail( "Client Took Too Long To Connect" );
break;
}
}
await Task.Delay( 1000 );
var singleClient = Connected.First();
singleClient.SendMessage( "Hey?" );
await Task.Delay( 100 );
singleClient.SendMessage( "Anyone?" );
await Task.Delay( 100 );
singleClient.SendMessage( "What's this?" );
await Task.Delay( 100 );
singleClient.SendMessage( "What's your status?" );
await Task.Delay( 10 );
singleClient.SendMessage( "Greetings!!??" );
await Task.Delay( 100 );
singleClient.SendMessage( "Hello Client!?" );
sw = System.Diagnostics.Stopwatch.StartNew();
while ( Connected.Contains( singleClient ) )
{
Receive();
await Task.Delay( 100 );
if ( sw.Elapsed.TotalSeconds > 10 )
{
Assert.Fail( "Socket Took Too Long" );
break;
}
}
await Task.Delay( 1000 );
Close();
}
public override unsafe void OnMessage( Connection connection, NetIdentity identity, IntPtr data, int size, long messageNum, long recvTime, int channel )
{
// We're only sending strings, so it's fine to read this like this
var str = UTF8Encoding.UTF8.GetString( (byte*)data, size );
Console.WriteLine( $"[SOCKET][{connection}[{identity}][{messageNum}][{recvTime}][{channel}] \"{str}\"" );
if ( str.Contains( "Hello, How are you" ) )
{
connection.SendMessage( "I'm great thanks, how about yourself?" );
}
if ( str.Contains( "bye" ) )
{
connection.SendMessage( "See you later, hater." );
connection.Flush();
connection.Close( true, 10, "Said Bye" );
}
}
}
} }
} }

View File

@ -0,0 +1,120 @@
using System;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Steamworks.Data;
namespace Steamworks
{
public partial class NetworkingSocketsTest
{
private class TestConnectionInterface : ConnectionInterface
{
public override void OnConnectionChanged( ConnectionInfo data )
{
Console.WriteLine( $"[Connection][{Connection}] [{data.State}]" );
base.OnConnectionChanged( data );
}
public override void OnConnecting( ConnectionInfo data )
{
Console.WriteLine( $" - OnConnecting" );
base.OnConnecting( data );
}
/// <summary>
/// Client is connected. They move from connecting to Connections
/// </summary>
public override void OnConnected( ConnectionInfo data )
{
Console.WriteLine( $" - OnConnected" );
base.OnConnected( data );
}
/// <summary>
/// The connection has been closed remotely or disconnected locally. Check data.State for details.
/// </summary>
public override void OnDisconnected( ConnectionInfo data )
{
Console.WriteLine( $" - OnDisconnected" );
base.OnDisconnected( data );
}
internal async Task RunAsync()
{
Console.WriteLine( "[Connection] RunAsync" );
var sw = System.Diagnostics.Stopwatch.StartNew();
while ( Connecting )
{
await Task.Delay( 10 );
if ( sw.Elapsed.TotalSeconds > 30 )
break;
}
if ( !Connected )
{
Console.WriteLine( "[Connection] Couldn't connect!" );
Console.WriteLine( Connection.DetailedStatus() );
return;
}
Console.WriteLine( "[Connection] Hey We're Connected!" );
sw = System.Diagnostics.Stopwatch.StartNew();
while ( Connected )
{
Receive();
await Task.Delay( 100 );
if ( sw.Elapsed.TotalSeconds > 10 )
{
Assert.Fail( "Client Took Too Long" );
break;
}
}
}
public override unsafe void OnMessage( IntPtr data, int size, long messageNum, long recvTime, int channel )
{
// We're only sending strings, so it's fine to read this like this
var str = UTF8Encoding.UTF8.GetString( (byte*) data, size );
Console.WriteLine( $"[Connection][{messageNum}][{recvTime}][{channel}] \"{str}\"" );
if ( str.Contains( "Hello" ) )
{
Connection.SendMessage( "Hello, How are you!?" );
Connection.SendMessage( "How do you like 20 messages in a row?" );
for ( int i=0; i<20; i++ )
{
Connection.SendMessage( $"BLAMMO!" );
}
}
if ( str.Contains( "status" ))
{
Console.WriteLine( Connection.DetailedStatus() );
}
if ( str.Contains( "how about yourself" ) )
{
Connection.SendMessage( "I'm great, but I have to go now, bye." );
}
if ( str.Contains( "hater" ) )
{
Close();
}
}
}
}
}

View File

@ -0,0 +1,119 @@
using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Steamworks.Data;
namespace Steamworks
{
public partial class NetworkingSocketsTest
{
private class TestSocketInterface : SocketInterface
{
public bool HasFinished = false;
public override void OnConnectionChanged( Connection connection, ConnectionInfo data )
{
Console.WriteLine( $"[Socket{Socket}][{connection}] [{data.State}]" );
base.OnConnectionChanged( connection, data );
}
public override void OnConnecting( Connection connection, ConnectionInfo data )
{
Console.WriteLine( $" - OnConnecting" );
base.OnConnecting( connection, data );
}
/// <summary>
/// Client is connected. They move from connecting to Connections
/// </summary>
public override void OnConnected( Connection connection, ConnectionInfo data )
{
Console.WriteLine( $" - OnConnected" );
base.OnConnected( connection, data );
}
/// <summary>
/// The connection has been closed remotely or disconnected locally. Check data.State for details.
/// </summary>
public override void OnDisconnected( Connection connection, ConnectionInfo data )
{
Console.WriteLine( $" - OnDisconnected" );
base.OnDisconnected( connection, data );
}
internal async Task RunAsync()
{
var sw = System.Diagnostics.Stopwatch.StartNew();
while ( Connected.Count == 0 )
{
await Task.Delay( 10 );
if ( sw.Elapsed.TotalSeconds > 5 )
{
Assert.Fail( "Client Took Too Long To Connect" );
break;
}
}
await Task.Delay( 1000 );
var singleClient = Connected.First();
singleClient.SendMessage( "Hey?" );
await Task.Delay( 100 );
singleClient.SendMessage( "Anyone?" );
await Task.Delay( 100 );
singleClient.SendMessage( "What's this?" );
await Task.Delay( 100 );
singleClient.SendMessage( "What's your status?" );
await Task.Delay( 10 );
singleClient.SendMessage( "Greetings!!??" );
await Task.Delay( 100 );
singleClient.SendMessage( "Hello Client!?" );
sw = System.Diagnostics.Stopwatch.StartNew();
while ( Connected.Contains( singleClient ) )
{
Receive();
await Task.Delay( 100 );
if ( sw.Elapsed.TotalSeconds > 10 )
{
Assert.Fail( "Socket Took Too Long" );
break;
}
}
await Task.Delay( 1000 );
Close();
}
public override unsafe void OnMessage( Connection connection, NetIdentity identity, IntPtr data, int size, long messageNum, long recvTime, int channel )
{
// We're only sending strings, so it's fine to read this like this
var str = UTF8Encoding.UTF8.GetString( (byte*)data, size );
Console.WriteLine( $"[SOCKET][{connection}[{identity}][{messageNum}][{recvTime}][{channel}] \"{str}\"" );
if ( str.Contains( "Hello, How are you" ) )
{
connection.SendMessage( "I'm great thanks, how about yourself?" );
}
if ( str.Contains( "bye" ) )
{
connection.SendMessage( "See you later, hater." );
connection.Flush();
connection.Close( true, 10, "Said Bye" );
}
}
}
}
}

View File

@ -11,10 +11,28 @@ public class SocketInterface
public List<Connection> Connected = new List<Connection>(); public List<Connection> Connected = new List<Connection>();
public Socket Socket { get; internal set; } public Socket Socket { get; internal set; }
public bool Close() => Socket.Close();
public override string ToString() => Socket.ToString(); public override string ToString() => Socket.ToString();
internal HSteamNetPollGroup pollGroup;
internal void Initialize()
{
pollGroup = SteamNetworkingSockets.Internal.CreatePollGroup();
}
public bool Close()
{
if ( SteamNetworkingSockets.Internal.IsValid )
{
SteamNetworkingSockets.Internal.DestroyPollGroup( pollGroup );
Socket.Close();
}
pollGroup = 0;
Socket = 0;
return true;
}
public virtual void OnConnectionChanged( Connection connection, ConnectionInfo data ) public virtual void OnConnectionChanged( Connection connection, ConnectionInfo data )
{ {
switch ( data.State ) switch ( data.State )
@ -40,6 +58,8 @@ public virtual void OnConnecting( Connection connection, ConnectionInfo data )
{ {
connection.Accept(); connection.Accept();
Connecting.Add( connection ); Connecting.Add( connection );
SteamNetworkingSockets.Internal.SetConnectionPollGroup( connection, pollGroup );
} }
/// <summary> /// <summary>
@ -67,10 +87,10 @@ public void Receive( int bufferSize = 32 )
int processed = 0; int processed = 0;
IntPtr messageBuffer = Marshal.AllocHGlobal( IntPtr.Size * bufferSize ); IntPtr messageBuffer = Marshal.AllocHGlobal( IntPtr.Size * bufferSize );
/*
try try
{ {
processed = SteamNetworkingSockets.Internal.ReceiveMessagesOnListenSocket( Socket, messageBuffer, bufferSize ); processed = SteamNetworkingSockets.Internal.ReceiveMessagesOnPollGroup( pollGroup, messageBuffer, bufferSize );
for ( int i = 0; i < processed; i++ ) for ( int i = 0; i < processed; i++ )
{ {
@ -81,7 +101,7 @@ public void Receive( int bufferSize = 32 )
{ {
Marshal.FreeHGlobal( messageBuffer ); Marshal.FreeHGlobal( messageBuffer );
} }
*/
// //
// Overwhelmed our buffer, keep going // Overwhelmed our buffer, keep going

View File

@ -73,9 +73,10 @@ internal static void SetConnectionInterface( uint id, ConnectionInterface iface
internal static void InstallEvents( bool server = false ) internal static void InstallEvents( bool server = false )
{ {
Dispatch.Install<SteamNetConnectionStatusChangedCallback_t>( x => ConnectionStatusChanged( x ), server ); Dispatch.Install<SteamNetConnectionStatusChangedCallback_t>( ConnectionStatusChanged, server );
} }
private static void ConnectionStatusChanged( SteamNetConnectionStatusChangedCallback_t data ) private static void ConnectionStatusChanged( SteamNetConnectionStatusChangedCallback_t data )
{ {
// //
@ -107,6 +108,8 @@ private static void ConnectionStatusChanged( SteamNetConnectionStatusChangedCall
var t = new T(); var t = new T();
var options = new NetKeyValue[0]; var options = new NetKeyValue[0];
t.Socket = Internal.CreateListenSocketIP( ref address, options.Length, options ); t.Socket = Internal.CreateListenSocketIP( ref address, options.Length, options );
t.Initialize();
SetSocketInterface( t.Socket.Id, t ); SetSocketInterface( t.Socket.Id, t );
return t; return t;
} }

View File

@ -94,27 +94,5 @@ public string DetailedStatus()
return strVal; return strVal;
} }
/*
[ThreadStatic]
private static SteamNetworkingMessage_t[] messageBuffer;
public IEnumerable<SteamNetworkingMessage_t> Messages
{
get
{
if ( messageBuffer == null )
messageBuffer = new SteamNetworkingMessage_t[128];
var num = SteamNetworkingSockets.Internal.ReceiveMessagesOnConnection( this, ref messageBuffer, messageBuffer.Length );
for ( int i = 0; i < num; i++)
{
yield return messageBuffer[i];
messageBuffer[i].Release();
}
}
}*/
} }
} }

View File

@ -24,7 +24,12 @@ public static implicit operator SteamId( NetIdentity value )
return value.steamID; return value.steamID;
} }
public override string ToString() => $"{type};{m_cbSize};{steamID}"; public override string ToString()
{
var id = this;
SteamNetworkingUtils.Internal.SteamNetworkingIdentity_ToString( ref id, out var str );
return str;
}
internal enum IdentityType internal enum IdentityType
{ {

View File

@ -17,7 +17,7 @@ public struct Socket
/// </summary> /// </summary>
public bool Close() public bool Close()
{ {
return SteamNetworkingSockets.Internal.CloseListenSocket( this ); return SteamNetworkingSockets.Internal.CloseListenSocket( Id );
} }
public SocketInterface Interface public SocketInterface Interface