/// <summary> /// Обработка полученной команды. Производится в другом потоке для использования многоядерности /// </summary> /// <param name="handler">Сокет</param> /// <param name="BaseCommands">Экземпляры команд</param> /// <param name="Log">Журнал</param> private static void RunCommand(Socket handler, List <Commands.ExecutableCommand> BaseCommands, Commands.Log Log) { string data = null; // Мы дождались клиента, пытающегося с нами соединиться // Получаем длину текстового сообщения byte[] SL_Length_b = new byte[4]; handler.Receive(SL_Length_b); int SL_Length = BitConverter.ToInt32(SL_Length_b, 0); // Получаем текстовую часть сообщения byte[] bytes = new byte[SL_Length]; int bytesRec = handler.Receive(bytes); data += Encoding.UTF8.GetString(bytes, 0, bytesRec); string[] data_parse = data.Split("\n"[0]); // Показываем данные на консоли Console.Write($"Полученный текст: «{data}»\n\n"); // Очистка ото всех уже не активных пользователей, которые почему-то не удалены из списка активных Active_Users.RemoveAll(x => x.Dead()); // Ищем пользователя по его логину и защитной записи. // Если дана команда входа в систему, то поиск не производим. User CurUser = null; if (data_parse[0].Trim() != Commands.Account.LoginAll) { CurUser = GetCurUser(data_parse[1], data_parse[2]); if (CurUser == null) { SendMsg(handler, Commands.Answer.StartMsg); SendMsg(handler, Commands.Answer.LoginExp); SendMsg(handler, Commands.Answer.EndMsg); handler.Shutdown(SocketShutdown.Both); handler.Close(); GC.Collect(); return; } } // Записываем в журнал команду. // Сохраняем все переданные параметры в одну строку через перенос каретки string Params = ""; for (int i = 3; i < data_parse.Count(); i++) { if (i > 3) { Params += "\n"; } if ((data_parse[0].Trim() == Commands.Account.LoginAll) && (data_parse[i].StartsWith("password "))) { Params += "*****"; } else { Params += data_parse[i]; } } // И добавляем в лог int LogID = Log.SaveQuery(handler, CurUser, data_parse[0], Params); // Обработка классом Commands. string[] Command = data_parse[0].Split('.'); bool Executed = false; // Выполним операцию, если команда требует стандартных параметров foreach (Commands.IStandartCommand Block in BaseCommands.OfType <Commands.IStandartCommand>()) { if (Command[0].ToLower() == Block.To <Commands.ExecutableCommand>().Name) { Block.Execute(handler, CurUser, Command, GetParameters(data_parse)); Executed = true; break; } } // Выполним операцию, если команда требует расширенных параметров foreach (Commands.IUserListCommand Block in BaseCommands.OfType <Commands.IUserListCommand>()) { if (Command[0].ToLower() == Block.To <Commands.ExecutableCommand>().Name) { Block.Execute(handler, CurUser, Command, GetParameters(data_parse), Active_Users, LogID); Executed = true; break; } } if (!Executed) { new Commands.Global(DataBase).Execute(handler, CurUser, Command, GetParameters(data_parse), LogID); } FinishConnection(handler); }
/// <summary> /// Базовый функционал программы. /// </summary> /// <param name="args"></param> static void Main(string[] args) { try { //Подключаемся к БД DataBase = new DB(DB_Server, DB_Name, DB_User, DB_Pass); Console.WriteLine("Подключение к MySQL: 127.0.0.1:3306"); } catch { Console.WriteLine("Ошибка подключения к БД"); } // Создаём классы для обработки команд List <Commands.ExecutableCommand> BaseCommands = new List <Commands.ExecutableCommand>() { new Commands.Account(DataBase), new Commands.Database(DataBase), new Commands.FileEngine(DataBase), new Commands.Laboratories(DataBase), new Commands.Log(DataBase), new Commands.Molecules(DataBase), new Commands.Users(DataBase), new Commands.Status(DataBase) }; Commands.Log Log = (Commands.Log)(BaseCommands.Where(x => x.Name == "log").ToArray()[0]); // Открываем файл-ключ CommonAES = (AES_Data)AES_Data.LoadFromFile("vector.bin"); // Устанавливаем для сокета локальную конечную точку IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 11000); // Создаем сокет Tcp/Ip Socket sListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // Назначаем сокет локальной конечной точке и слушаем входящие сокеты try { sListener.Bind(ipEndPoint); sListener.Listen(10); Console.WriteLine("Старт сервера"); // Завершаем все сеансы сообщением о падении сервера. DataBase.ExecuteQuery(@"UPDATE `sessions` SET `quit_date` = CURRENT_TIMESTAMP(), `reason_quit` = 'Server Fail – quit date of restart' WHERE `quit_date` IS NULL;"); // Начинаем слушать соединения while (true) { Console.WriteLine($"Ожидаем соединение через порт {ipEndPoint}"); // Программа приостанавливается, ожидая входящее соединение Socket handler = sListener.Accept(); Task NewCommandRun = Task.Run(() => RunCommand(handler, BaseCommands, Log)); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } finally { Console.ReadLine(); } }
/// <summary> /// Запускает прослушивание порта /// </summary> public void Start() { Enabled = true; try { //Подключаемся к БД DataBase = new DB(DB_Server, DB_Name, DB_User, DB_Pass); Log($"Подключение к службе MySQL: {DB_Server}:3306"); } catch { Exception E = new Exception("Ошибка подключения к БД"); } // Создаём классы для обработки команд List <Commands.ExecutableCommand> BaseCommands = new List <Commands.ExecutableCommand>() { new Commands.Account(DataBase), new Commands.Database(DataBase), new Commands.FileEngine(DataBase), new Commands.Laboratories(DataBase), new Commands.Log(DataBase), new Commands.Molecules(DataBase), new Commands.Users(DataBase), new Commands.Status(DataBase) }; Log("Создание команд"); Commands.Log LogCmd = (Commands.Log)(BaseCommands.Where(x => x.Name == "log").ToArray()[0]); Log("Создание команды Log"); // Открываем файл-ключ try { CommonAES = (AES_Data)Serializable.LoadFromFile(Path.Combine( Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "vector.bin")); Log("открытие ключа"); } catch (Exception e) { Log(e.Message); } // Устанавливаем для сокета локальную конечную точку IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 11000); // Создаем сокет Tcp/Ip Socket sListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); Log("Создание сокета"); // Назначаем сокет локальной конечной точке и слушаем входящие сокеты try { sListener.Bind(ipEndPoint); sListener.Listen(10); Log("Старт сервера"); // Завершаем все сеансы сообщением о падении сервера. DataBase.ExecuteQuery(@"UPDATE `sessions` SET `quit_date` = CURRENT_TIMESTAMP(), `reason_quit` = 'Server Fail – quit date of restart' WHERE `quit_date` IS NULL;"); // Начинаем слушать соединения while (Enabled) { Log($"Ожидаем соединение через порт {ipEndPoint}"); // Программа приостанавливается, ожидая входящее соединение Socket handler = sListener.Accept(); Log($"Сигнал получен. Передаём в отдельный поток"); //Task NewCommandRun = Task.Run(() => RunCommand(handler, BaseCommands, LogCmd)); RunCommand(handler, BaseCommands, LogCmd); } } catch (Exception ex) { Log(ex.ToString()); } finally { } }