 |
|

30.01.2017, 04:29
|
|
Участник форума
Регистрация: 24.11.2015
Сообщений: 165
С нами:
5509192
Репутация:
1457
|
|
Нашел более менее оптимальный вариант, проектирование систем на основе акторов, в java.
Для простоты и прозрачности, логики, все поведение програмируется внутренними классами.
Реализовал базовый набор по Hewitt-у, во время обработки сообщения, актор может:
- отправлять сообщения другим акторам и самому себе(рекурсивное сообщение) (метод Context.send и Reference.send)
- менять свое поведения (метод Context.become)
- создавать других акторов (метод Context.create)
О поведении актора, на основе просто примере будет более наглядно:
Сообщение от Спойлер
Код:
Код:
package fact.samples;
import fact.Context;
public class Account implements Context {
final String login;
final String password;
Account(String login, String password) {
this.login = login;
this.password = password;
}
public void define() {
become("Free");
}
public void logout() {
System.out.println("wrong logout");
}
public class Free {
public void login(String login, String password) {
if(Account.this.login.equals(login) && Account.this.password.equals(password)) {
System.out.println("login success");
become("Login");
} else
System.out.println("wrong login or password");
}
}
public class Login {
public void login(String login, String password) {
System.out.println("account in use");
}
public void logout() {
System.out.println("logout");
become("Free");
}
}
}
В данном коде, есть актор Account, у которого, есть два поведения(внутренних класса) Free и Login. У каждого из них есть, свои обработчики сообщений.
Если расширить данный пример, можно реализовать актор для сервера авторизации.
Замечание: если пришло сообщение, которого нету в заданном поведение, то метод для обработки сообщения ищеться в базов классе. В данном примере, если отправить сообщение logout, когда актор установлен как Free, будет вызван обработчик из базового класса Account, на экран консоли, выведиться сообщение "wrong logout"
Пример использования:
Сообщение от Спойлер
Код:
Код:
package fact.samples;
import fact.Context;
import fact.Model;
import fact.Reference;
public class AccountSample implements Context {
public void define() {
Reference account = create("account", new Account("root", "root"));
account.send("logout");
account.send("login", "root", "1243");
account.send("login", "root", "root");
account.send("login", "root", "root");
account.send("logout");
account.send("logout");
account.send("login", "root", "root");
}
public static void main(String...args) {
Model.launch(new AccountSample());
}
}
console output:
Код:
Код:
wrong logout
wrong login or password
login success
account in use
logout
wrong logout
login success
|
|
|

30.01.2017, 08:50
|
|
Участник форума
Регистрация: 24.11.2015
Сообщений: 165
С нами:
5509192
Репутация:
1457
|
|
- Добавил отправку сообщений с задержкой
Сообщение от Спойлер
Код:
Код:
package fact.samples;
import fact.Context;
import fact.Model;
public class CounterDelay implements Context {
private long count = 0;
public void define() {
send("print").delay(1000);
send("tick");
}
public void tick() {
count++;
send("tick");
}
public void print() {
System.out.println(count);
count = 0;
send("print").delay(1000);
}
public static void main(String...args) {
Model.launch(new CounterDelay());
}
}
В данном примере, актор отправляет себе два сообщение:
- print с задержкой 1сек
- tick без задержок
оба сообщения рекурсивны. На каждое сообщения tick, увеличивается счетчик, на каждое сообщения print отображается показатель счетчика и затем сбрасывается на ноль.
Заложил сетевой фреймворм, на основе java.nio.
Для простого примера реализавал, ехо сервер.
|
|
|

01.02.2017, 21:05
|
|
Участник форума
Регистрация: 24.11.2015
Сообщений: 165
С нами:
5509192
Репутация:
1457
|
|
Обновил. "немного" переделал код. Интерфейс остался обратно совместимый. Исключение запросы.
- добавил полный цикл обслуживания актора create/stop/resume/terminate(kill).
При остановке, возврате или удаленния актора, можно устанавливать,обратный вызов, функция которая будет вызвана, в случае успешной операции.
Примечани: Функции обратного вызова должны быть определенны в классе актора.
|
|
|

01.02.2017, 21:33
|
|
Участник форума
Регистрация: 24.11.2015
Сообщений: 165
С нами:
5509192
Репутация:
1457
|
|
Управление запросами
Для запрос к другому актору, нужно объявить класс-поведение, и задать методы с возможной сигнатурой ответа. При вызове метода request, возвращается объект Future, в котором черем метод handle, нужно указать имя поведения, для обработки ответа.
Внимание: если не указать поведение, то запрсов не выполниться.
При ответе, актор может получить сообщения типа reply или complaint, в классе-поведения обрабатывающий запрос, нужно покрыть возможные варианты сигнатуры сообщения.
Пример:
Есть актор Account, в котором присутсвует медот-обработчик login. При обработке сообщения, если данные логина и пароля, соответсвует данным аккаунта, то Account отправляет объект LoginSuccess, если не правильные данные, то отвечает через метод complaint, отправляет LoginFail.WrongLoginOrPassword.
Сообщение от Спойлер
Код:
Код:
package fact.samples;
import fact.Context;
public class AccountRequest implements Context {
private String login;
private String password;
public AccountRequest(String login, String password) {
this.login = login;
this.password = password;
}
public void login(String login, String password) {
if(this.login.equals(login) && this.password.equals(password)) {
reply(success);
} else
complaint(LoginFail.WrongLoginOrPassword);
}
public static class LoginSuccess {
private LoginSuccess() { }
}
private final static LoginSuccess success = new LoginSuccess();
public enum LoginFail {
WrongLoginOrPassword,
AccountInUse
}
}
В акторе который производит запрос, присутсвует класс поведения Request, в котором определенны два обработчика, на успешный запрос и провальный запрос. Для простоты, создаем актор-аккаунт, на месте.
В примере показывается, что вовремя запроса, актор будет обрабатывать, только ответ. Другие сообщения обрабатываются после запроса, то есть актор блогируется для обработки входящих сообщения, за исключение ответа на запрос.
Сообщение от Спойлер
Код:
Код:
public class RequestSample implements Context {
Reference account;
public void define() {
account = create("account", new AccountRequest("root", "root"));
account.request("login", "login", "login").handle("Request");
send("tick");
send("print");
}
public void tick() {
account.request("login", "root", "root").handle("Request");
send("print");
}
public void print() {
System.out.println("print");
}
public class Request {
public void reply(LoginFail fail) {
System.out.println("login failed");
}
public void reply(LoginSuccess success) {
System.out.println("login success");
}
}
public static void main(String...args) {
Model.launch(new RequestSample());
}
}
История вычислений данного примера:
[QUOTE="Спойлер"]
[COLOR="#363940"]
0 E AccountRequest
|
|
|

02.02.2017, 01:22
|
|
Участник форума
Регистрация: 24.11.2015
Сообщений: 165
С нами:
5509192
Репутация:
1457
|
|
- Переделал сетвой API. Реализовал пример эхо сервера.( Соединение отправляет каждые 100 мс строку, сервер читает её отображает на консоль и отправляет обратно, клиент читае и отображает на консоль)
- Переместил сетевой API в репозиторий ядра.
- Добавил методы для определения типа сообщения(запрос, ответ, ответ-ошибка)
|
|
|

02.02.2017, 12:34
|
|
Участник форума
Регистрация: 24.11.2015
Сообщений: 165
С нами:
5509192
Репутация:
1457
|
|
Обновил:
- реализовал цепочку запросов
- реализовал передачу запрос(continuation)
- реализовал управляющие методы статическим путем, объявленны в fact.ActorContext. Теперь можно получить доступ к управляющим метода чере import static
Добавил соответствующие примеры
|
|
|

02.02.2017, 23:00
|
|
Участник форума
Регистрация: 24.11.2015
Сообщений: 165
С нами:
5509192
Репутация:
1457
|
|
Исправиль некоторые ошибки.
Немного lineage. Написал каркас для сервера авторизации.(interlude)
Нужно организовать
- работу с базой данных
- работу с игровыми серверами. Написать, proxy для игрового сервера.
- переписать сетевую библиотеку, организовать чтение по требованию.
ПС: Для меня не понятно, каким образом работает реализация, криптографии, добавление контрольной суммы и шифровка первого пакет xor ключем. Отсутвует
смешение, для задания предела, самое интересное, если подать буффер в котором, уже записанно, минимум 4 байта, то криптография накроется медным тазом. У меня закрались дикие сомнения, что реализация на l2j, если её топорным путем перенести на С не будет работать, так как в jvm зануляет все значения в созданных массивах. Понятно, что в сервере авторизаии, может быть только один пакен на запись и один на чтение, по протоколу, но это всеравно не делает менее ужасней эту криптографию.
Не могу понять почему выдает ошибку контрольной суммы, переодически... магия...
ПС Двойная авторизация, в l2j вообще кабздец, как так можно было сделать. Ошибка, котороя тянется на все сборки
|
|
|

02.02.2017, 23:30
|
|
Участник форума
Регистрация: 01.02.2017
Сообщений: 210
С нами:
4882736
Репутация:
0
|
|
[OFF]Тема одного актёра?[/OFF]
|
|
|

02.02.2017, 23:39
|
|
Познавший АНТИЧАТ
Регистрация: 07.11.2015
Сообщений: 1,730
С нами:
5534362
Репутация:
1617
|
|
[OFF]
Сообщение от Attme
[OFF]Тема одного актёра?[/OFF]
а ты присоединись [/OFF]
|
|
|

02.02.2017, 23:45
|
|
Флудер
Регистрация: 20.01.2015
Сообщений: 7,201
С нами:
5952720
Репутация:
6527
|
|
Сообщение от Attme
[OFF]Тема одного актёра?[/OFF]
Человек описывает свою работу, не нравится внесите свою лепту
|
|
|
|
 |
|
|
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
|
|
|
|