private void OnAccept() { // 处理连接 NetworkConnection c; while ((c = Driver.Accept()) != default) { // New connection can never have any events, if this one does - just close it if (c.PopEvent(Driver, out _) != NetworkEvent.Type.Empty) { c.Disconnect(Driver); continue; } Debug.Log($"Accepted a connection:{Driver.RemoteEndPoint(c).Address}"); ++ConnectionCount; ++_connectionInstanceId; // 创建session var session = PostUpdateCommands.CreateEntity(); PostUpdateCommands.AddComponent(session, new NetworkSnapshotAckComponent()); PostUpdateCommands.AddComponent(session, new NetworkStreamConnection { Value = c }); PostUpdateCommands.AddComponent(session, new CommandTargetComponent()); PostUpdateCommands.AddComponent(session, new NetworkIdComponent { Value = _connectionInstanceId }); PostUpdateCommands.AddBuffer <IncomingRpcDataStreamBufferComponent>(session); PostUpdateCommands.AddBuffer <IncomingCommandDataStreamBufferComponent>(session); var outBuffer = PostUpdateCommands.AddBuffer <OutgoingRpcDataStreamBufferComponent>(session); // 发送id _rpcQueue.Schedule(outBuffer, new RpcSetNetworkId { id = _connectionInstanceId }); } }
public unsafe void Execute() { for (int index = 0; index < connections.Length; index++) { DataStreamReader stream; if (!connections[index].IsCreated) { continue; } NetworkEvent.Type cmd; while ((cmd = driver.PopEventForConnection(connections[index], out stream)) != NetworkEvent.Type.Empty) { if (cmd == NetworkEvent.Type.Data) { // First byte is the messageType MessageType messageType = (MessageType)stream.ReadByte(); switch (messageType) { case MessageType.StartServer: { // Check if they are already connected or perhaps are already hosting, if so return if (HasPeer(index) || connectionIndexToRoomID.ContainsKey(index)) { return; } Client client = new Client { ConnectionId = index, IsServer = true, OutgoingBytes = 0, ConnectTime = DateTime.UtcNow }; Room room = new Room { RoomId = GenerateRoomId(), Server = client, }; rooms.Add(room); connectionIndexToRoomID.Add(index, room.RoomId); NativeList <byte> ipv6AddressBuffer = new NativeList <byte>(16, Allocator.Temp); NetworkEndPoint ipAddress = driver.RemoteEndPoint(connections[index]); if (ipAddress.Family == NetworkFamily.Ipv6) { string ipv6Address = ipAddress.Address.Split(':')[0]; foreach (string n in ipv6Address.Split('.')) { ipv6AddressBuffer.Add(Byte.Parse(n)); } } else if (ipAddress.Family == NetworkFamily.Ipv4) { string ipv4Address = ipAddress.Address.Split(':')[0]; foreach (byte b in new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255 }) { ipv6AddressBuffer.Add(b); } foreach (string n in ipv4Address.Split('.')) { ipv6AddressBuffer.Add(Byte.Parse(n)); } } else { // TODO: Throw wrong type ipv6AddressBuffer = default(NativeList <byte>); } ipAddress.SetRawAddressBytes(ipv6AddressBuffer, NetworkFamily.Ipv6); serverAddressToRoomID.Add(ipAddress.Address, room.RoomId); if (ServerBehaviour.Config.EnableRuntimeMetaLogging) { Console.WriteLine("[INFO] Server started from " + ipAddress.Address); } DataStreamWriter writer; writer = driver.BeginSend(pipeline, connections[index]); // Write the message type writer.WriteByte((byte)MessageType.AddressReport); // Write the Connection Id writer.WriteInt(index); // TODO: Throw if address is not 16 bytes. It should always be // Write the address writer.WriteBytes(ipv6AddressBuffer); // Write the port writer.WriteUShort(ipAddress.Port); // Send connect to client driver.EndSend(writer); ipv6AddressBuffer.Dispose(); } break; case MessageType.ConnectToServer: { // Check if they are already connected or perhaps are already hosting, if so return if (HasPeer(index) || connectionIndexToRoomID.ContainsKey(index)) { return; } NativeArray <byte> addressBytes = new NativeArray <byte>(16, Allocator.Temp); stream.ReadBytes(addressBytes); ushort remotePort = stream.ReadUShort(); NetworkEndPoint endpoint = new NetworkEndPoint(); endpoint.SetRawAddressBytes(addressBytes, NetworkFamily.Ipv6); endpoint.Port = remotePort; if (ServerBehaviour.Config.EnableRuntimeMetaLogging) { Console.WriteLine("[INFO] Connection requested to address " + endpoint.Address); } if (serverAddressToRoomID.ContainsKey(endpoint.Address)) { if (ServerBehaviour.Config.EnableRuntimeMetaLogging) { Console.WriteLine("[INFO] Connection approved"); } // Get the room they want to join Room room = GetRoom(serverAddressToRoomID[endpoint.Address]); // Create a client for them Client client = new Client { ConnectionId = index, IsServer = false, OutgoingBytes = 0, ConnectTime = DateTime.UtcNow }; // Handle the connect HandleClientConnect(room, client); } } break; case MessageType.Data: { foreach (Room room in rooms) { if (HasPeer(room, index, out bool isServer)) { // Found a matching client in room if (isServer) { // The server is sending data int destination = stream.ReadInt(); // Safety check. Make sure who they want to send to ACTUALLY belongs to their room if (HasPeer(room, destination, out isServer) && !isServer) { Send(room, destination, index, stream); } } else { // A client is sending data Send(room, room.ServerConnectionId, index, stream); } } } } break; case MessageType.ClientDisconnect: { int clientConnectionId = stream.ReadInt(); if (ServerBehaviour.Config.EnableRuntimeMetaLogging) { Console.WriteLine("[INFO] Client disconnect request"); } foreach (Room room in rooms) { if (room.ServerConnectionId == clientConnectionId && HandleClientDisconnect(room, clientConnectionId, true)) { // Only disconnect one. A peer can only be in 1 room break; } } } break; } } else if (cmd == NetworkEvent.Type.Disconnect) { Console.WriteLine("[INFO] Client disconnected from server"); connections[index] = default(NetworkConnection); } } } }