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

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

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

Восстановить пароль

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

Ответ
 
Опции темы Поиск в этой теме
Старый 23.06.2010, 20:23   #481
Shouldercannon
Участник клуба Подтвердите свой е-майл
 
Аватар для Shouldercannon
 
Регистрация: 26.01.2008
Сообщений: 1,899
По умолчанию

Спасибо. Теперь работает как надо, но опять началось мучание списка юзеров как в случае с диапазонами (пост #457 работа с меткой).
Shouldercannon вне форума Ответить с цитированием
Старый 23.06.2010, 20:28   #482
Beermonza
Инженер ИС
Старожил
 
Аватар для Beermonza
 
Регистрация: 13.12.2006
Сообщений: 2,671
По умолчанию

Доводите код до рабочего, что еще посоветовать...
Основные вопросы мы разобрали, теперь дело техники.
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его
Beermonza вне форума Ответить с цитированием
Старый 24.06.2010, 08:55   #483
Shouldercannon
Участник клуба Подтвердите свой е-майл
 
Аватар для Shouldercannon
 
Регистрация: 26.01.2008
Сообщений: 1,899
По умолчанию

Применить способ с меткой и CheckConnect? Применить его в // Код приема ника клиента?

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

Вот смотрите, ...когда пользователь подключился, и он не попадает в диапазон, происходит отключение, т.е. connect -> disconnect, в чат он не попадает, обновление списка не происходит. Если пользователь в диапазон попадает, его приходится впускать в чат, ...обновление запущено, он записан в массив, но не определен как пользователь. Сервер шлет запрос, и ответ приходит, в case 1: таймера узнается, что он имеет недопустимый ник, его отключают, ...нужно снова проверить пользователей, срабатывает обновление, снова список меняется (пользователя теперь нет в списке).
К чему я все это пишу, а не показываю кодом? ...хочу вас научить думать и самостоятельно принимать решения.
Итак, какие у вас мысли? ...что можно сделать, чтобы список не тревожить?
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его
Beermonza вне форума Ответить с цитированием
Старый 24.06.2010, 23:07   #485
Shouldercannon
Участник клуба Подтвердите свой е-майл
 
Аватар для Shouldercannon
 
Регистрация: 26.01.2008
Сообщений: 1,899
По умолчанию

1.
Цитата:
Сообщение от Beermonza Посмотреть сообщение
Вот смотрите, ...когда пользователь подключился, и он не попадает в диапазон, происходит отключение, т.е. connect -> disconnect, в чат он не попадает, обновление списка не происходит. Если пользователь в диапазон попадает, его приходится впускать в чат, ...обновление запущено, он записан в массив, но не определен как пользователь. Сервер шлет запрос, и ответ приходит, в case 1: таймера узнается, что он имеет недопустимый ник, его отключают, ...нужно снова проверить пользователей, срабатывает обновление, снова список меняется (пользователя теперь нет в списке).
К чему я все это пишу, а не показываю кодом? ...хочу вас научить думать и самостоятельно принимать решения.
Итак, какие у вас мысли? ...что можно сделать, чтобы список не тревожить?
Может создать флаг, запрещающий в данном случает обновление.

2. Заметил, если сервер убить через диспетчер залач, то клиент выполняя данный код
Код:
...
procedure TForm1.ClException(Sender: TObject; Error: Exception);
begin
  if (Error.ClassName = 'ESocketError') then
    begin
      // Снова пытаемся подключиться через таймер 1 раз в 5 секунд
      StatusBar1.Panels[1].Text := '';
      StatusBar1.Panels[2].Text := '[' + TimeToStr(Now) + '] Ожидание подключения к серверу...';
      UserListView.Clear;
      ConnectTimer.Enabled := True;
    end
    else
      Application.ShowException(Error); // Ошибки не сокета пусть показывает
end;
...
procedure TForm1.ConnectTimerTimer(Sender: TObject);
begin
  ClientSocket.Active := True;
end;
не переподключается.
Может нужно вместо ClientSocket.Active := True; использовать
Код:
procedure TForm1.ConnectToChat;
begin
  // Запишем указанный порт в ClientSocket
  ClientSocket.Port := StrToInt(ChatPort);

  // Запишем хост и адрес (одно значение ChatHost в оба)
  ClientSocket.Host := ChatHost;
  ClientSocket.Address := ChatHost;

  // Запускаем клиента
  ConnectTimer.Enabled := True;
  // Изменяем тэг
  ChatConnectStatus := True;
end;

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

Цитата:
Сообщение от Shouldercannon
Может создать флаг, запрещающий в данном случает обновление.
Нужно сразу после закрытия канала, по случаю совпадения ника, перепрыгнуть в конец кода секции case, минуя обработку забаненых IP, запись в список (Rec, Autores) и обработку админов.

Цитата:
Сообщение от Shouldercannon
2. Заметил, если сервер убить через диспетчер задач, то клиент выполняя данный код не переподключается.
У меня клиент понимает, что сервер пропал, будучи закрытым как положено или с завершением процесса через диспетчер задач, ...если ошибка сокета, пытается подключиться пока не подключится к вновь созданному серверу, и ничего не делает, если это было корректное завершение работы сервера, ...просто констатирует факт закрытия сервера.
Таймер реконнекта нужно отключать у клиента в событии ClientSocketConnect, там должно быть изначально прописано (по моим исходникам).
Процедура ClException - это перехват сообщений, чтобы сервер не выводил сообщения связанные с ошибками сокета, иначе будут стопоры пока не нажмешь "ok".
Если клиентский сокет посчитал пропажу сервера за корректный disconnect, то никаких переподключений не будет, в событии ClientSocketDisconnect ничего не прописано.
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его

Последний раз редактировалось Beermonza; 25.06.2010 в 16:04.
Beermonza вне форума Ответить с цитированием
Старый 25.06.2010, 23:44   #487
Shouldercannon
Участник клуба Подтвердите свой е-майл
 
Аватар для Shouldercannon
 
Регистрация: 26.01.2008
Сообщений: 1,899
По умолчанию

1.
Цитата:
Нужно сразу после закрытия канала, по случаю совпадения ника, перепрыгнуть в конец кода секции case, минуя обработку забаненых IP, запись в список (Rec, Autores) и обработку админов.
Код:
procedure TForm1.ServerTimerTimer(Sender: TObject);
Label G; // Метка (Игнор обновления списка юзеров при входе запрещённых клиентов)
...
              0: begin
                // Определение комманд
                case com2 of
                // Код приема ника клиента
                0: begin
                  // Запишем в массив полученный ник
                  UserMas[i].Name := Copy(text, 3, len);

                  // Проверка на наличие одинаковых ников
                  for i4 := 1 to ServerSocket.Socket.ActiveConnections do
                    begin
                      if (UserMas[i4].Name = UserMas[i].Name) and (i4 <> i) then
                        begin
                          ServerSocket.Socket.Connections[i - 1].Close;
                          GoTo G; // Переход в метку
                          Break;
                        end;
                    end;

                  // Начало опасного блока, могущего вызывать слипание команд
                  // Обработка забаненых IP
                  for c := 0 to 255 do
                    begin
                      if BanIPMas[c] = ServerSocket.Socket.Connections[i - 1].RemoteAddress then
                        ServerSocket.Socket.Connections[i - 1].SendText('21');

                      Break;
                    end;
                  // Конец опасного блока

                  // Отметим, что пользователь записан в список
                  UserMas[i].Rec := True;
                  // Отметим авторизацию счетчиком
                  Inc(Autores);

                  // Обработка админов
                  for c := 0 to 255 do
                    begin
                      if AdminIPMas[c] = ServerSocket.Socket.Connections[i - 1].RemoteAddress then
                        UserMas[i].Admin := True;
                    end;

                  G: // Сюда перейдёт программа
                end;

                end;
              end;
Список по прежнему обновляется

2.
Цитата:
У меня клиент понимает, что сервер пропал, будучи закрытым как положено или с завершением процесса через диспетчер задач, ...если ошибка сокета, пытается подключиться пока не подключится к вновь созданному серверу, и ничего не делает, если это было корректное завершение работы сервера, ...просто констатирует факт закрытия сервера.
Специально завершаю работу сервера через Диспетчер задач вызывая ошибку сокета
Код:
procedure TForm1.ClException(Sender: TObject; Error: Exception);
begin
  if (Error.ClassName = 'ESocketError') then
    begin
      // Снова пытаемся подключиться через таймер 1 раз в 5 секунд
      StatusBar1.Panels[1].Text := '';
      StatusBar1.Panels[2].Text := '[' + TimeToStr(Now) + '] Ожидание подключения к серверу...';
      UserListView.Clear;
      ConnectTimer.Enabled := True;
    end
    else
      Application.ShowException(Error); // Ошибки не сокета пусть показывает
end;

procedure TForm1.ConnectTimerTimer(Sender: TObject);
begin
  ClientSocket.Active := True;
end;
Подключение происходит, но непонятно к чему, а к заново созданному серверу подключения так и нет.

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

1. Смотрите где вызываются обновления. Там где есть UpdMas := True;. Такое у сервера в ServerSocketClientConnect. После того как произошло событие подключения клиента, в конце таймера запустится процедура обновления массива UpdateUserMas. В ней будет создана запись, что "есть неизвестный клиент", на него отправится запрос "кто такой?", обнулится счетчик Autores.
Каждый ответ клиентов на авторизацию будет считать авторизированных. UpdateUserList в конце таймера запуститься только тогда, когда все клиенты корректно авторизируются. Если хоть один из них не пройдет код:

Код:
UserMas[i].Rec := True;
Inc(Autores);
то, обновления списка не будет. А мы знаем, что по совпадению ника, условие выполняет прыжок в метку G:.
По совпадению ника канал закрывается, вызывая событие ServerSocketClientDisconnect, в котором тоже есть флаг обновления UpdMas := True;, ...он заставляет снова проверить массив, т.е. один клиент отпал по условию совпадения ника, его запись из массива UserMas удаляется, и снова всем пользователям отсылается запрос "кто такой?". Все клиенты отвечают, Autores всех считает. На этот раз все авторизировались корректно, в конце таймера условие запустит обновление списка UpdateUserList.
Как этого избежать? ...а надо ли? ...может в момент манипуляции с нежелательным клиентом произойдут еще какие-нибудь изменения, а сервер, проверяя по массиву кто не прошел авторизацию, упустит важный момент обновления списка, ...а?
Вообще, приходится прибегнуть к слежению за сокетом и реагированием на каждое событие (событие возвращает сокет, который его вызвал), что нарушает сам принцип построения этой системы клиент сервер, когда сервер не реагирует на клиентов вне очереди и не выполняет команды немедленно, а ставит всех в очередь, дисциплинирует, и не дает над собой издеваться многочисленными запросами.
Делайте ваш выбор.

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

Цитата:
1. Смотрите где вызываются обновления. Там где есть UpdMas := True;. Такое у сервера в ServerSocketClientConnect. После того как произошло событие подключения клиента, в конце таймера запустится процедура обновления массива UpdateUserMas. В ней будет создана запись, что "есть неизвестный клиент", на него отправится запрос "кто такой?", обнулится счетчик Autores.
Каждый ответ клиентов на авторизацию будет считать авторизированных. UpdateUserList в конце таймера запуститься только тогда, когда все клиенты корректно авторизируются. Если хоть один из них не пройдет код:

Код:

UserMas[i].Rec := True;
Inc(Autores);

то, обновления списка не будет. А мы знаем, что по совпадению ника, условие выполняет прыжок в метку G:.
По совпадению ника канал закрывается, вызывая событие ServerSocketClientDisconnect, в котором тоже есть флаг обновления UpdMas := True;, ...он заставляет снова проверить массив, т.е. один клиент отпал по условию совпадения ника, его запись из массива UserMas удаляется, и снова всем пользователям отсылается запрос "кто такой?". Все клиенты отвечают, Autores всех считает. На этот раз все авторизировались корректно, в конце таймера условие запустит обновление списка UpdateUserList.
Как этого избежать? ...а надо ли? ...может в момент манипуляции с нежелательным клиентом произойдут еще какие-нибудь изменения, а сервер, проверяя по массиву кто не прошел авторизацию, упустит важный момент обновления списка, ...а?
Вообще, приходится прибегнуть к слежению за сокетом и реагированием на каждое событие (событие возвращает сокет, который его вызвал), что нарушает сам принцип построения этой системы клиент сервер, когда сервер не реагирует на клиентов вне очереди и не выполняет команды немедленно, а ставит всех в очередь, дисциплинирует, и не дает над собой издеваться многочисленными запросами.
Делайте ваш выбор.
Если бы не бан выдающийся по первому совпавшему значению, то не надо было. А так сидят два Васи, а даю бан второму, а получает первый, хотя они с разных IP. Тоже с личкой будет (сообщение будет приходить не тому). Если бы можно было присваивать ID по IP было бы круто, тогда можно и с одинаковыми никами пускать.

Цитата:
2. А если после создания вновь сервера с клиента (что находился в ожидании подключения из-за пропажи сервера) послать сообщение, он вызовет корректную работу?
Изображения
Тип файла: gif SError.gif (7.0 Кб, 80 просмотров)

Последний раз редактировалось Shouldercannon; 26.06.2010 в 17:37.
Shouldercannon вне форума Ответить с цитированием
Старый 26.06.2010, 20:13   #490
Beermonza
Инженер ИС
Старожил
 
Аватар для Beermonza
 
Регистрация: 13.12.2006
Сообщений: 2,671
По умолчанию

Очевидно, пропажа сервера у вас не фиксируется в системе как ошибка сокета, иначе бы последовало незамедлительное переподключение, и попытки дальнейших подключений с интервалом таймера. Добавьте в тело условия процедуры ClException отправку "0" на сервер, ...это должно повторно вызвать ошибку сокета, может ваша ОС не фиксирует некорректную пропажу сервера, а сообщение вызовет ошибку на стороне клиента, ...должно сработать.

По поводу сообщения "Windows socket error", оно просто не должно появляться на экране, ClException отлавливает такие сообщения, ...если только вы не запускаете проект из под Delphi.
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его
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