Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Клуб программистов > Обсуждение статей
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 01.06.2010, 22:37   #401
Shouldercannon
Участник клуба Подтвердите свой е-майл
 
Аватар для Shouldercannon
 
Регистрация: 26.01.2008
Сообщений: 1,897
По умолчанию

Хочу сделать простую админку. Вот как она будет работать.
Будет создан массив с IP на подобии как у бан. При конекте будет производиться сверка IP, если такой есть, то отсылаем клиенту команду, допуска к админке. У клиента в свою очередь появятся два новых пункта в меню: Забанить и разбанить.
Как всё будет работать.
Клиент в своём списке выбирает ник и жмёт забанить. Далее формируем строку:
код команды + (разделитель) + ник забанившего + (разделитель) + ник забаненного. Сервер получив всё это дело приступает к поиску ника, найдя его он берёт IP (с учётом того, что помимо ника в списке юзеров имеют IP) и отправляет на него команду бана и рассылает всем юзерам уведомление о бане. Такая же система с разбаном.
Вопросы:
1. Данную задачу реально выполнить на данном чате
2. Проверку производить на наличие админки в коде приема ника клиента, как и с баном
Shouldercannon вне форума Ответить с цитированием
Старый 02.06.2010, 00:46   #402
Beermonza
Инженер ИС
Старожил
 
Аватар для Beermonza
 
Регистрация: 13.12.2006
Сообщений: 2,671
По умолчанию

Цитата:
Сообщение от Shouldercannon Посмотреть сообщение
Вопросы:
1. Данную задачу реально выполнить на данном чате ?
2. Проверку производить на наличие админки в коде приема ника клиента, как и с баном ?
1. Этот чат ограничений на изобретательность не накладывает.
2. Пусть клиент, если он может быть админом, посылает на сервер свой ник и пароль, ...сервер кроме этих двух параметров проверит и IP-адрес, ...если все 3 параметра совпадут для удаленного администрирования, то впускать клиента и сделать ему пометку, что он админ (запись, создайте как нужно вам), сервер принимая определенного типа команды, как управленческие, проверяет "на админа" клиента, что их посылает. Только не забывайте очищать записи при каждом входе и выходе клиентов, иначе все постепенно "станут" админами.
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его
Beermonza вне форума Ответить с цитированием
Старый 02.06.2010, 00:59   #403
Shouldercannon
Участник клуба Подтвердите свой е-майл
 
Аватар для Shouldercannon
 
Регистрация: 26.01.2008
Сообщений: 1,897
По умолчанию

У меня всё будет определяться только по IP. Клиенты будут получать админку проходя через
Код:
                              {Код приема ника клиента}
                              1: begin
                                {Запишем в массив полученный ник}
                                UserMas[i].Name := Copy(text, 2, len);
                                  {Обработка забаненых IP}
                                  for n := 0 to 255 do
                                    begin
                                      if BanIPMas[n] = ServerSocket.Socket.Connections[i - 1].RemoteAddress then
                                        ServerSocket.Socket.Connections[i - 1].SendText('4');
                                    end;
                                      {Обработка админов}
                                      for n := 0 to 255 do
                                        begin
                                          if AdminIPMas[n] = ServerSocket.Socket.Connections[i - 1].RemoteAddress then
                                            ServerSocket.Socket.Connections[i - 1].SendText('8');
                                        end;
                                          {Отметим, что пользователь записан в список}
                                          UserMas[i].Rec := True;
                                            {Отметим авторизацию счетчиком }
                                            Inc(Autores);
                              end;
При таком раскладе если у подключившегося бан и админка, то не выводится список юзеров. Проверку делать на дачу админки в событии ServerTimer или ServerSocketClientConnect и не очень понял какие записи очищать? Можно ли использовать одинаковую цифру команды сервером и клиентом? Например сервер отсылает 5 (бан) на клиент, а клиент посылает на сервер тоже 5 (принять ник разбаненого).

Последний раз редактировалось Shouldercannon; 02.06.2010 в 04:23.
Shouldercannon вне форума Ответить с цитированием
Старый 02.06.2010, 16:06   #404
Beermonza
Инженер ИС
Старожил
 
Аватар для Beermonza
 
Регистрация: 13.12.2006
Сообщений: 2,671
По умолчанию

Цитата:
Сообщение от Shouldercannon
Проверку делать на дачу админки в событии ServerTimer или ServerSocketClientConnect...
В ServerTimer, ведь пользователь должен войти в чат как простой пользователь, затем его проверят на администрирование.
В ServerSocketClientConnect должна быть только служба блокирования нежелательных IP-адресов, т.е. если пользователя ни при каких условиях нельзя запускать (тот же ддосер например).
Цитата:
Сообщение от Shouldercannon
... и не очень понял какие записи очищать?
В процедуре UpdateUserMas, в ней первыми строками идет очистка прежней информации. Создайте в типе TUserList запись Admin: Boolean, она будет отвечать за администрацию, True - администратор, Flase - нет. Вот часть обновления:
Код:
procedure TForm1.UpdateUserMas;
begin
  If ServerSocket.Socket.ActiveConnections > 0 then
    Begin
// очищаем массив
      For i:=1 to 255 do
        Begin
          UserMas[i].Status := 0;
          UserMas[i].Admin := False; // не администратор
        end;

......

    end;

.....

end;
Как только при идентификации пользователя по IP узнается что он админ, запись Admin переводите в True. Для чего это нужно? ...поскольку проверка на администрирование проходит один раз, то нужен флаг, чтобы использовать его потом повсеместно, не проверяя постоянно по списку при каждой отправке/приему пакетов, ...достаточно будет проверять флаг администратора. Например, ...пришла команда типа "7", она относится к управленческим, сервер приняв ее проверяет запись Admin пользователя, если она True, он выполняет команду, иначе - блокирует пользователя, или как-то сигнализирует, что клиент пытается управлять сервером. Таких команд будет достаточно, и проверять каждый раз по списку не рационально, посему пользуемся флагом админа, и не забываем про его очистку.

Цитата:
Сообщение от Shouldercannon
Можно ли использовать одинаковую цифру команды сервером и клиентом? Например сервер отсылает 5 (бан) на клиент, а клиент посылает на сервер тоже 5 (принять ник разбаненого).
Можно, главное чтобы вы не запутались потом, код хоть и одинаковый, состав пакета может быть разным.
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его
Beermonza вне форума Ответить с цитированием
Старый 02.06.2010, 18:32   #405
Shouldercannon
Участник клуба Подтвердите свой е-майл
 
Аватар для Shouldercannon
 
Регистрация: 26.01.2008
Сообщений: 1,897
Вопрос

Цитата:
Цитата:Сообщение от Shouldercannon
... и не очень понял какие записи очищать?

В процедуре UpdateUserMas, в ней первыми строками идет очистка прежней информации. Создайте в типе TUserList запись Admin: Boolean, она будет отвечать за администрацию, True - администратор, Flase - нет. Вот часть обновления:
Код:

procedure TForm1.UpdateUserMas;
begin
If ServerSocket.Socket.ActiveConnectio ns > 0 then
Begin
// очищаем массив
For i:=1 to 255 do
Begin
UserMas[i].Status := 0;
UserMas[i].Admin := False; // не администратор
end;

......

end;

.....

end;
Как только при идентификации пользователя по IP узнается что он админ, запись Admin переводите в True. Для чего это нужно? ...поскольку проверка на администрирование проходит один раз, то нужен флаг, чтобы использовать его потом повсеместно, не проверяя постоянно по списку при каждой отправке/приему пакетов, ...достаточно будет проверять флаг администратора. Например, ...пришла команда типа "7", она относится к управленческим, сервер приняв ее проверяет запись Admin пользователя, если она True, он выполняет команду, иначе - блокирует пользователя, или как-то сигнализирует, что клиент пытается управлять сервером. Таких команд будет достаточно, и проверять каждый раз по списку не рационально, посему пользуемся флагом админа, и не забываем про его очистку.
То ли я торможу или мы друг друга не понимаем . По данной системе я понял, что на каждом клиенте есть элементы упраления сервером и каждый может ими свободно воспользоваться, А данная система призвана разрешить управление только тем, чей IP занесён в админлист. Если расклад действительно таков, то в моём случае элементы управления сервером доступны на клиенте только тем, кто получил команду их активации с сервера. Если и это не верно, то я действительно торможу .

И я никак не могу понять почему если на одного юзера посылаются две команды (бан и админ), то у него не заполняется UserListView при данном
Код:
...
BanIP, AdminIP: TStringList;
BanIPMas, AdminIPMas: array[0..255] of string;
...
procedure TForm1.UpdateBanMassiv;
var
n: Integer;
begin
FillChar(BanIPMas, sizeof(BanIPMas), 0); {Очистка массива}
  for n := 0 to BanIP.count - 1 do
    BanIPMas[n] := (BanIP[n]);
end;

procedure TForm1.UpdateAdminMassiv;
var
n: Integer;
begin
FillChar(AdminIPMas, sizeof(AdminIPMas), 0); {Очистка массива}
  for n := 0 to AdminIP.count - 1 do
    AdminIPMas[n] := (AdminIP[n]);
end;
...
{Код приема ника клиента}
                              1: begin
                                {Запишем в массив полученный ник}
                                UserMas[i].Name := Copy(text, 2, len);
                                  {Обработка забаненых IP}
                                  for n := 0 to 255 do
                                    begin
                                      if BanIPMas[n] = ServerSocket.Socket.Connections[i - 1].RemoteAddress then
                                        ServerSocket.Socket.Connections[i - 1].SendText('4'); {Команда забанить юзера}
                                    end;
                                      {Обработка админов}
                                      for n := 0 to 255 do
                                        begin
                                          if AdminIPMas[n] = ServerSocket.Socket.Connections[i - 1].RemoteAddress then
                                            ServerSocket.Socket.Connections[i - 1].SendText('8'); {Команда на активацию админки}
                                        end;
                                          {Отметим, что пользователь записан в список}
                                          UserMas[i].Rec := True;
                                            {Отметим авторизацию счетчиком }
                                            Inc(Autores);
                              end;
Подозрение падает на n

Последний раз редактировалось Shouldercannon; 02.06.2010 в 18:40.
Shouldercannon вне форума Ответить с цитированием
Старый 02.06.2010, 21:29   #406
Beermonza
Инженер ИС
Старожил
 
Аватар для Beermonza
 
Регистрация: 13.12.2006
Сообщений: 2,671
По умолчанию

По поводу отправки с сервера после того как клиент ответил на запрос сервера на идентификацию:

Код:
{Код приема ника клиента}
                              1: begin
                                {Запишем в массив полученный ник}
                                UserMas[i].Name := Copy(text, 2, len);
                                  {Обработка забаненых IP}
                                  for n := 0 to 255 do
                                    begin
                                      if BanIPMas[n] = ServerSocket.Socket.Connections[i - 1].RemoteAddress then
                                        ServerSocket.Socket.Connections[i - 1].SendText('4'); {Команда забанить юзера}
                                    end;
                                      {Обработка админов}
                                      for n := 0 to 255 do
                                        begin
                                          if AdminIPMas[n] = ServerSocket.Socket.Connections[i - 1].RemoteAddress then
                                            ServerSocket.Socket.Connections[i - 1].SendText('8'); {Команда на активацию админки}
                                        end;
                                          {Отметим, что пользователь записан в список}
                                          UserMas[i].Rec := True;
                                            {Отметим авторизацию счетчиком }
                                            Inc(Autores);
                              end;
...команды Send идут практически одновременно, не будет отдельной команды "4" и отдельной "8", сервер пришлет один пакет "48", это заслуга TCP/IP, дабы снизить трафик и не выполнять действия ради действий, она пропихивает сразу всю информацию, которая идет подряд. Именно по этому я организовал таймер, чтобы не допускать слеплевания пакетов, чтобы их не разлеплять потом на стороне клиента по некоторому алгоритму.
Почему не заполняется лист? ...давайте посмотрим на такт таймера. Значит после срабатывания у сервера пункта 1: сервер пытается отослать сразу два пакета по 1 байту, которые соединяются в один двухбайтовый, ...смотрим ниже, в конце такта срабатывает флаг на обновление списка, запускается процедура UpdateUserList, котора готовит пакет с кодом 2+строка пользователей, ...а мы помним, что это еще тот же такт, значит к двухбайтовому пакету "48" добавляется пакет "2+строка", т.е. фактически с сервера уходит пакет "482+строка пользователей", ...не удивительно, что клиент не обновляет список, он ждет просто "2+строка пользователей".

Все управленческие команды должны быть отвязаны от команд на идентификацию. Пункт 1: принадлежит к такого рода командам, в нем не должно быть никаких отправок клиентам.

Что делать? ...в пункте 1: таймера сервера проверка на бан и админа, но только исключительно в записях массива пользователя, ничего не отсылая. Клиент должен нажимать некую клавишу "я админ" и присылать запрос под некоторым кодом. У сервера этот пункт должен начинаться с проверки записи Admin, если она ложная, слать ему сообщение, что он не может быть админам, кроме того любой запрос клиента на сервер должен проверяться на бан (кроме "1"), ...если забаненый клиент входит, он принимается как обычный пользователь, тут же проводится проверка на админа и бан, условия срабатывают, изменяются статусы, сервер шлет всем список пользователей, в котором уже числится кто админ, кто забанен. Как только клиент попытается прислать сообщение, если он забанен, условие проверки по флагу вышлет ему команду на блокировку.
Если он не забанен, но админ, его нажатие на кнопку "я админ" пошлет на сервер запрос по некоторой команде, сервер проверит запись на админа, отошлет ему сообщение что он админ, может откроет ему формочку дополнительную, и все команды с нее всегда будет проверять на флаг админа. Понятно?
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его

Последний раз редактировалось Beermonza; 02.06.2010 в 21:35.
Beermonza вне форума Ответить с цитированием
Старый 02.06.2010, 21:53   #407
Shouldercannon
Участник клуба Подтвердите свой е-майл
 
Аватар для Shouldercannon
 
Регистрация: 26.01.2008
Сообщений: 1,897
По умолчанию

Цитата:
Все управленческие команды должны быть отвязаны от команд на идентификацию. Пункт 1: принадлежит к такого рода командам, в нем не должно быть никаких отправок клиентам.
как исключение кроме этого, с ним пока всё нормально
Код:
                                  {Код приема ника клиента}
                                  1: begin
                                    {Запишем в массив полученный ник}
                                    UserMas[i].Name := Copy(text, 2, len);
                                      {Обработка забаненых IP}
                                      for n := 0 to 255 do
                                        begin
                                          if BanIPMas[n] = ServerSocket.Socket.Connections[i - 1].RemoteAddress then
                                            ServerSocket.Socket.Connections[i - 1].SendText('4');
                                        end;

Последний раз редактировалось Shouldercannon; 02.06.2010 в 21:57.
Shouldercannon вне форума Ответить с цитированием
Старый 02.06.2010, 22:46   #408
Beermonza
Инженер ИС
Старожил
 
Аватар для Beermonza
 
Регистрация: 13.12.2006
Сообщений: 2,671
По умолчанию

Цитата:
Сообщение от Shouldercannon Посмотреть сообщение
как исключение кроме этого, с ним пока всё нормально
Код:
                                  {Код приема ника клиента}
                                  1: begin
                                    {Запишем в массив полученный ник}
                                    UserMas[i].Name := Copy(text, 2, len);
                                      {Обработка забаненых IP}
                                      for n := 0 to 255 do
                                        begin
                                          if BanIPMas[n] = ServerSocket.Socket.Connections[i - 1].RemoteAddress then
                                            ServerSocket.Socket.Connections[i - 1].SendText('4');
                                        end;
Не факт, что будет срабатывать сто раз из ста, ...может быть проход двух отдельных пакетов связано с тормозами сети или ПК, иначе, всегда будет слипание пакетов.
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его
Beermonza вне форума Ответить с цитированием
Старый 03.06.2010, 00:21   #409
Shouldercannon
Участник клуба Подтвердите свой е-майл
 
Аватар для Shouldercannon
 
Регистрация: 26.01.2008
Сообщений: 1,897
Восклицание

Цитата:
Почему не заполняется лист? ...давайте посмотрим на такт таймера. Значит после срабатывания у сервера пункта 1: сервер пытается отослать сразу два пакета по 1 байту, которые соединяются в один двухбайтовый, ...смотрим ниже, в конце такта срабатывает флаг на обновление списка, запускается процедура UpdateUserList, котора готовит пакет с кодом 2+строка пользователей, ...а мы помним, что это еще тот же такт, значит к двухбайтовому пакету "48" добавляется пакет "2+строка", т.е. фактически с сервера уходит пакет "482+строка пользователей", ...не удивительно, что клиент не обновляет список, он ждет просто "2+строка пользователей".
Проверил на практике, сначала приходит команда 4, потои 82+строка пользователей Как вариант можно сделесть обработку команды 82 .
Цитата:
может быть проход двух отдельных пакетов связано с тормозами сети или ПК
Тест всегд провожу по локалке (проблем со скоростью быть не должно), проц не сильный, но и не слабый AMD Athlon 64 3000+, хотя может быть всё что угодно, если получится на 4-х ядерном опробую .
Я конкретно напортачил в коде и походу не правильно реализовал отправку команд бар/разбан для удалённого управления. Запустил сервер и пять клиентов. Забанил с третьего клиента одного из юзеров в этого получилось месиво и после поочерёдного выхода клиентов опять отсылается 4, потом 82+строка пользователей.
Вложения
Тип файла: txt Удалённое управление.txt (6.2 Кб, 151 просмотров)
Тип файла: txt Результат после бана.txt (1.7 Кб, 149 просмотров)

Последний раз редактировалось Shouldercannon; 03.06.2010 в 15:01.
Shouldercannon вне форума Ответить с цитированием
Старый 03.06.2010, 16:05   #410
Beermonza
Инженер ИС
Старожил
 
Аватар для Beermonza
 
Регистрация: 13.12.2006
Сообщений: 2,671
По умолчанию

Пакеты, состоящие из повторяющихся секций, означают только одно - программист не следит за открытием и закрытием секций циклов. Обратите внимание на число повторений, их 5, и клиентов 5, какой-то цикл вобрал в себя не свою секцию кода.
Я всегда советую соблюдать дистанцию, грамотно расставлять строки. Вне специальных структур строки должны идти с одним и тем же отступом, отступ делается только тогда, когда секция кода находится в промежутке Begin..End, все циклические структуры, имеющие внутри себя более одной строки, всегда заключаются в Begin..End:

Код:
For i := 0 to 15 do
  Begin
    a := Pos(Chr(156), text);
    AdminNick := Copy(text, 2, a - 2);
    text2 := Copy(text, a + 1, length(text));
    b := Pos(Chr(161), text2);
    BannedUnbannedNick := Copy(text2, 1, b - 1);
    AdminReason := Copy(text2, b + 1, length (text2));
  end;
Если коды разделяются по задаче, то они подписываются комментарием и разделяются пустой строкой:

Код:
For i := 0 to 15 do
  Begin
    // Отобразим сообщение в RVChat
    RVChat.AddTextFromNewLine('[' + TimeToStr(Now) + '] ', 2);
    RVChat.AddText(AdminNick, 6);

    // Записываем имя и увеличиваем значение счетчика
    MasL.Add(AdminNick);
    RVChat.AddText(': забанил ' + BannedUnbannedNick + '. Причина: ' + AdminReason + '.', 7);
    RVChat.Reformat;

    If AutoscrollChat = True then RVChat.Perform(WM_VSCROLL, SB_BOTTOM, 0);
  end;
Фигурные скобки применяются исключительно для кода, чтобы отключать не нужные участки внутри строк:

Код:
For i := 0 to 15 do
  Begin
    BannedUnbannedNick := Copy({text2} s, 1, b - 1);

    // Записываем имя и увеличиваем значение счетчика
    MasL.Add(AdminNick);
{    RVChat.AddText(': забанил ' + BannedUnbannedNick + '. Причина: ' + AdminReason + '.', 7);
    RVChat.Reformat;
    If AutoscrollChat = True then RVChat.Perform(WM_VSCROLL, SB_BOTTOM, 0);   }
  end;
Бывает так, что в коде добрых две сотни строк, которые на время нужно отключить, ...тут и помогают фигурные скобки.

Вернемся к вашей проблеме, вот участок кода:

Код:
{Обработка забаненого удалённым администратором}
8: begin
 {Заполняем AdminNick, BannedUnbannedNick, AdminReason}
 a := Pos(Chr(156), text);
   AdminNick := Copy(text, 2, a - 2);
     text2 := Copy(text, a + 1, length(text));
       b := Pos(Chr(161), text2);
         BannedUnbannedNick := Copy(text2, 1, b - 1);
           AdminReason := Copy(text2, b + 1, length (text2));
             {Поиск IP по нику}
             for m := 0 to UserListView.Items.Count - 1 do
               if Pos(BannedUnbannedNick, UserListView.Items.Item[m].Caption) <> 0 then
                 begin
                   BanIP.Add(Copy(UserListView.Items.Item[m].SubItems.Text, 1, length(UserListView.Items.Item[m].SubItems.Text) - 2));
                     ServerSocket.Socket.Connections[ServerSocket.Socket.ActiveConnections - 1].SendText('4');
                     ...

                     {Разошлем сообщение пользователям (кроме того, кто прислал)}
                     for j := 0 to ServerSocket.Socket.ActiveConnections - 1 do
                       begin
                         if (j + 1) <> i then
                           ServerSocket.Socket.Connections[j].SendText('0' + AdminNick + Chr(140) + ': забанил ' + BannedUnbannedNick
                                                                                          + '. Причина: ' + AdminReason + '.');
                       end;
               end;
end;
Постоянный сдвиг каждой строки сбивает зрение, тяжело отличить структуры от простых строк, ...я подправил и сразу увидел ошибку.

Продолжение в следующем сообщении...
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его

Последний раз редактировалось Beermonza; 03.06.2010 в 16:41.
Beermonza вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
обновление в блоге - Создание клиент-сервера Pblog Обсуждение статей 0 03.10.2007 17:12
обновление в блоге - Диплом. Создание и продвижение сайта - готовь сани летом, а дипл Pblog Обсуждение статей 0 31.08.2007 20:00
обновление в блоге - USB Холодильник Pblog Обсуждение статей 0 25.06.2007 14:13
обновление в блоге - О ярлыках Pblog Обсуждение статей 0 27.05.2007 03:17