kerryjiang / SuperSocket

SuperSocket is a light weight, cross platform and extensible socket server application framework.
Apache License 2.0
3.9k stars 1.15k forks source link

supersocket 2.0 with unity3d 2022.3 #691

Open jessienms opened 9 months ago

jessienms commented 9 months ago

supersocket 2.0.0 unity3d 2022.3.13f1

I am currently building a server using SuperSocket and creating a game project in Unity3d to implement a feature that connects and exchanges packets. When I run the same code in a general .NET console project, the packet reception works without any problems, but when I run the same code in Unity3D, send works but recv does not.

When debugging in Unity3d, the PipeChannel.ReadPipeAsync task is executed, but when PipeReader.ReadAsync is finished and pipeChannel.ReaderBuffer is called below, the state of the buffer is all filled with 0, so a protocol error occurs.

Could you give me some advice on this problem?

kerryjiang commented 8 months ago

It looks like network protocol issue. Which kind of protocol do you use?

penspanic commented 6 months ago

I'm facing this issue too. Versions tested - 2.0.0-beta.18(nuget), 2.0.0-beta.20.440(myget)

Could anyone give me some advice?

kerryjiang commented 5 months ago

Could you point the code you debugged?

wangruoyi1996 commented 4 months ago

I solved it. ` public class MyTcpPipeConnection : TcpPipeConnection {

private System.Net.Sockets.Socket m_Socket;

public MyTcpPipeConnection(System.Net.Sockets.Socket socket, ConnectionOptions options) : base(socket, options)
{
    m_Socket = socket;
}

protected override async ValueTask<int> FillPipeWithDataAsync(Memory<byte> memory, CancellationToken cancellationToken)
{
    return await MyReceiveAsync(m_Socket, memory, SocketFlags.None, cancellationToken);
}

private async ValueTask<int> MyReceiveAsync(System.Net.Sockets.Socket socket, Memory<byte> memory, SocketFlags socketFlags, CancellationToken cancellationToken)
{
    MemoryMarshal.TryGetArray<byte>(memory, out ArraySegment<byte> buffer);
    return await socket.ReceiveAsync(buffer, socketFlags).ConfigureAwait(false);
}

} public class MyTcpConnectionFactory : TcpConnectionFactory { public MyTcpConnectionFactory(ListenOptions listenOptions, ConnectionOptions connectionOptions, Action socketOptionsSetter, IConnectionStreamInitializersFactory connectionStreamInitializersFactory) : base(listenOptions, connectionOptions, socketOptionsSetter, connectionStreamInitializersFactory) { }

public override async Task<IConnection> CreateConnection(object connection, CancellationToken cancellationToken)
{
    var socket = connection as System.Net.Sockets.Socket;

    ApplySocketOptions(socket);

    if (ConnectionStreamInitializers is IEnumerable<IConnectionStreamInitializer> connectionStreamInitializers
        && connectionStreamInitializers.Any())
    {
        var stream = default(Stream);

        foreach (var initializer in connectionStreamInitializers)
        {
            stream = await initializer.InitializeAsync(socket, stream, cancellationToken);
        }

        return new StreamPipeConnection(stream, socket.RemoteEndPoint, socket.LocalEndPoint, ConnectionOptions);
    }

    return new MyTcpPipeConnection(socket, ConnectionOptions);
}

} public class MyConnectionFactoryBuilder : ConnectionFactoryBuilder { public MyConnectionFactoryBuilder(SocketOptionsSetter socketOptionsSetter, IConnectionStreamInitializersFactory connectionStreamInitializersFactory) : base(socketOptionsSetter, connectionStreamInitializersFactory) { }

public override IConnectionFactory Build(ListenOptions listenOptions, ConnectionOptions connectionOptions)
{
    return new MyTcpConnectionFactory(listenOptions, connectionOptions, SocketOptionsSetter, ConnectionStreamInitializersFactory);
}

} ` Create the above three scripts, then add server configuration .ConfigureServices(options => { options.AddSingleton<IConnectionFactoryBuilder, MyConnectionFactoryBuilder>(); })

kerryjiang commented 3 weeks ago

I will try to understand the problem.

kerryjiang commented 3 weeks ago

@wangruoyi1996 @jessienms I only noticed one difference between @wangruoyi1996 's solution and SuperSocket's code.

The fix

MemoryMarshal.TryGetArray<byte>(memory, out ArraySegment<byte> buffer);

The SuperSocket

MemoryMarshal.TryGetArray(memory, out buffer);

SuperSocket get the generic type argument's type inferring instead of declaring the type directly. It looks like a compiling issue?

kerryjiang commented 3 weeks ago

Pushed a fix according to my guess: https://github.com/kerryjiang/SuperSocket/commit/f2e549db68902d8b1bf870ae7a4a29112c9e9606