Hello everyone,
this is my first post and i very tired trying solving this problem.
When a client disconnect, server try to send message on disconnected client returning a warning and other two errors. I’ve tryed to close all possible connection but error still remain.
I’m using NatPunchthrought script starting from this project:
this is the code:
public class NATServer : NetworkServerSimple
{
public override void Initialize()
{
base.Initialize();
// Use the custom connection class to prevent connectionId conflicts
SetNetworkConnectionClass<NATServerNetworkConnection>();
}
public override void OnConnected(NetworkConnection conn)
{
base.OnConnected(conn);
NetworkServer.AddExternalConnection(conn);
}
}
public class NATServerNetworkConnection : NetworkConnection
{
private int offset;
/*
* Add an offset to the connectionId. We first offset by the maxinum number of connections that the server expects
* and then further offset by the hostId since each additional host will only have one connection
*
*/
public override void Initialize(string networkAddress, int networkHostId, int networkConnectionId, HostTopology hostTopology)
{
offset = NetworkServer.hostTopology.MaxDefaultConnections + networkHostId;
base.Initialize(networkAddress, networkHostId, networkConnectionId + offset, hostTopology);
}
/*
* Instead of sending out on the NetworkServer we need to send out on
* the appropriate NATServer that the client connected to.
* We also un-offset the connectionId to get the id of the connection on the NATServer
*/
public override bool TransportSend(byte[] bytes, int numBytes, int channelId, out byte error)
{
// i can use "isReady" for track if client disconnected
return NetworkTransport.Send(hostId, connectionId - offset, channelId, bytes, numBytes, out error);
}
}
This is the custom classes used on project, now, my netManager custom class:
public class NetManager : NetworkManager
{
//-- SOME CODE --//
void Start()
{
//Check if instance already exists
if (instance == null)
//if not, set instance to this
instance = this;
//If instance already exists and it's not this:
else if (instance != this)
//Then destroy this. This enforces our singleton pattern, meaning there can only ever be one instance of a GameManager.
Destroy(gameObject);
//Sets this to not be destroyed when reloading scene
DontDestroyOnLoad(gameObject);
clientIDField = typeof(NetworkClient).GetField("m_ClientId", BindingFlags.NonPublic | BindingFlags.Instance);
natHelper = GetComponent<NATHelper>();
//settings for default connectionConfig to use
foreach (QosType type in base.channels)
connectionConfig.AddChannel(type);
}
//-- SOME CODE --//
// When the server gets the onHolePunchedServer callback it will be passed the port that you need to listen on.
void OnHolePunchedServer(int natListenPort)
{
NATServer newServer = new NATServer();
bool isListening = newServer.Listen(natListenPort, NetworkServer.hostTopology);
if (isListening)
natServers.Add(newServer);
}
//-- SOME CODE --//
/*
* When the client receives the onHolePunchedClient callback it will be passed two ports.
* You need to use the first port as the port the client is connecting from and the second port as the port the client is connecting to on the server.
*/
void OnHolePunchedClient(int natListenPort, int natConnectPort)
{
Debug.Log("OnHolePunchedClient");
// The port on the server that we are connecting to
networkPort = natConnectPort;
// Make sure to connect to the correct IP or things won't work
if (hostGameMM.external_ip == natHelper.externalIP)
{
if (hostGameMM.internal_ip == Network.player.ipAddress)
{
// Host is running on the same computer as client, two separate builds
networkAddress = "127.0.0.1";
}
else
{
// Host is on the same local network as client
networkAddress = hostGameMM.internal_ip;
}
}
else
{
// Host is somewhere out on the internet
networkAddress = hostGameMM.external_ip;
}
// Standard client setup stuff than the NetworkMager would normally take care of for us
NetworkTransport.Init(globalConfig);
/**
if (customConfig)
{
foreach (QosType type in base.channels)
connectionConfig.AddChannel(type);
}
else
{
connectionConfig..AddChannel(QosType.ReliableSequenced);
connectionConfig.AddChannel(QosType.Unreliable);
}*/
// If we try to use maxConnection when the Advanced Configuration checkbox is not checked
// we will get a crc mismatch because the host will have been started with the default
// max players of 8 rather than the value in maxConnections
//int maxPlayers = 8;
//if (customConfig)
// maxPlayers = maxConnections;
int maxPlayers = maxConnections;
HostTopology topo = new HostTopology(connectionConfig, maxPlayers);
// Start up a transport level host on the port that the hole was punched from
// This doesn’t actually add a “Host” like the HLAPI does. This command actually just starts up a socket, I’m pretty sure they should change the name of the method to AddSocket
int natListenSocketID = NetworkTransport.AddHost(topo, natListenPort);
// Create and configure a new NetworkClient
client = new NetworkClient();
client.Configure(topo);
// Connect to the port on the server that we punched through to
client.Connect(networkAddress, networkPort);
//NetworkTransport.RemoveHost((int)clientIDField.GetValue(client));
// Magic! Set the client's transport level host ID so that the client will use
// the host we just started above instead of the one it creates internally when we call Connect.
// This has to be done so that the connection will be made from the correct port, otherwise
// Unity will use a random port to connect from and NAT Punchthrough will fail.
// This is the shit that keeps me up at night.
clientIDField.SetValue(client, natListenSocketID);
// Tell Unity to use the client we just created as _the_ client so that OnClientConnect will be called
// and all the other HLAPI stuff just works. Oh god, so nice.
UseExternalClient(client);
GameManager.instance.isHost = false;
}
//-- SOME CODE --//
private void Update()
{
natServers.ForEach(server => server.Update());
}
WARNING: Attempt to send to not connected connection {1}
ERROR: Failed to send internal buffer channel:1 bytesToSend:27
ERROR: Send Error: WrongConnection channel:1 bytesToSend:27
Maybe i’m using wrong method to disconnect a client?
I’ve try to use conn.Disconnect(); conn.Dispose(); when a client disconnect but nothing. How i can stop transport.send when Update() pump Network?