/// <summary> /// ћетод, отправл¤ющий клиенту команду и утилизирующий еЄ обратно в буфер /// TODO перенести метод в IRemoteClient /// </summary> /// <param name="client"></param> /// <param name="action"></param> private void SendClientCommand(IRemoteClient client, Action <IRoomCommand> action) { IRoomCommand command = null; try { command = _pool.Get(); action(command); _log.Debug("SendCommand: " + command); client.SendCommand(command); } catch (Exception e) { _pool.Free(command); _log.Error("Error SendCommand:\n" + e.ToString()); } finally { if (command != null) { _pool.Free(command); } } }
/// <summary> /// ћетод, при получении сообщени¤ от клиента /// </summary> /// <param name="client"></param> /// <param name="command"></param> private void OnPushMessage(IRemoteClient client, IRoomCommand command) { if (client.RoomChannel == null) { client.Detach(); return; } //если у комнаты ещЄ не истекло врем¤, то отправл¤ем команду if (!client.RoomChannel.IsExpired) { client.RoomChannel.SendAll(command, c => c != client); } }
/// <summary> /// Метод, отправляем сообщение всем клиентам, кроме тех, что отсеит фильтер /// </summary> /// <param name="command"></param> /// <param name="filter"></param> public void SendAll(IRoomCommand command, Func <IRemoteClient, bool> filter) { LastClientAccess = DateTime.Now; lock (_clients) { //на foreach не переделывать!!! он тормозит, а метод критичен к производительности. for (var i = 0; i < _clients.Count; ++i) { if (filter(_clients[i])) { _clients[i].SendCommand(command); } } } }
private void OnClientCommand(IRoomClient client, IRoomCommand command) { Action <IRemoteClient, IRoomCommand> handlerAction; if (_handlers.TryGetValue(command.Command, out handlerAction)) { //ѕередача управлени¤ обработчику команды handlerAction((IRemoteClient)client, command); } else { //отключаем клиента, чтобы не слал что попало client.Detach(); } }
private void OnClientReceive(IRoomClient client, IRoomCommand command) { switch (command.Command) { case Commands.SetClientId: client.ClientId = command.Data["ClientId"]; SendClientCommand(client, cmd => { cmd.Command = Commands.EnterToRoom; cmd.Data["RoomId"] = client.Room; }); break; case Commands.PushMessage: break; } }
private void DoCommandProcess(IRoomCommand command) { try { //возбуждаем событие приема команды AfterReceive?.Invoke(this, command); } catch (Exception e) { LogException(e); } finally { //отправляем команду обратно в пул на переиспользование _poolCommand.Free(command); } }
/// <summary> /// лиент входит в комнату /// </summary> /// <param name="client"></param> /// <param name="command"></param> private void OnClientEnterToRoom(IRemoteClient client, IRoomCommand command) { //пытаемс¤ получить номер комнаты string roomId; if (!command.Data.TryGetValue("RoomId", out roomId)) { _log.ErrorFormat("Client {0} try create room with empty Id", client.ClientId); client.Detach(); return; } //устанавливаем номер комнаты client.Room = roomId; //возвращаем или создаем комнату var room = GetRoom(roomId) ?? CreateRoom(roomId); //добавл¤ем туда клиента room.Add(client); }
/// <summary> /// ћетод возвращает кортеж, состо¤щий из ссылки на массив и количества записанных в массив байт. /// ¬озвращенный массив нужно будет передать обратно в IPool<bytes[]>, так как он беретс¤ из пула /// </summary> /// <param name="command">“ранслируема¤ команда</param> /// <returns>ћассив бйат и количество записанных в него байт, начина¤ с индекса 0</returns> public Tuple <byte[], int> ToBuffer(IRoomCommand command) { if (command == null) { throw new ArgumentNullException(nameof(command)); } var sb = _stringPool.Get(); //записываем заголовок команды sb.Append(command.Command); sb.Append("|"); foreach (var pair in command.Data) { //записываем значени¤ из команды sb.Append(pair.Key); sb.Append("^"); sb.Append(pair.Value); sb.Append("|"); } //добавл¤ем хвост sb.Append('\0'); //сохран¤ем команду в строке var value = sb.ToString(); //отдаем обратно билдер sb.Length = 0; _stringPool.Free(sb); //записываем в выделенный буффер данные var buffer = _bytesPool.Get(); var length = Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, 0); return(new Tuple <byte[], int>(buffer, length)); }
private void SendClientCommand(IRoomClient client, Action <IRoomCommand> action) { IRoomCommand command = null; var pool = Container.Resolve <IPool <IRoomCommand> >(); try { command = pool.Get(); action(command); client.SendCommand(command); } catch (Exception e) { pool.Free(command); } finally { if (command != null) { pool.Free(command); } } }
/// <summary> /// Метод, отправляющий команду на сервер /// </summary> /// <param name="command"></param> public void SendCommand(IRoomCommand command) { var data = _protocol.ToBuffer(command); _baseSocketClient.SendBytes(data.Item1, data.Item2); }