Всем доброго времени суток.
Разрабатываю онлайн 3д игру, была выбрана платформа java. Для 3d был выбран движок jmonkeyengine.
А в качестве серверной части я решил написать простеньки p2p фреймворк, MVC с реализацией представлений на клиенте.
Где может пригодится:
1. Сервер для мобильных сервисов.
2. Любые многопользовательские приложения где нужно p2p.
3. Онлайн игры.
4. Торрент при желании.
Диаграмма:
Принцип работы:
1. Клиент посылает на сервер сообещение в котором перечисляются переменные и какую задачу вызвать.
2. Сообщение попадает очередь входящих сообщений.
3. Роутер запускает нужную задачу с этими переменными.
4. В задаче мы отправляем ответ пользователю.
Дополнительные возможности:
1. Настраивать порты клиента и сервера.
2. Модели базы данных.
3. Валидация входящих сообщений.
4. Права пользователей.
5. Модули.
6. Механизм сессий.
7. Команды.
8. Смена протокола tcp/udp.
Инструкции, примеры и документациия.
http://jsockframework.blogspot.ru/
https://github.com/nnpa/jsock/
youtube
Пример отправки и приема сообщений.
Клиент
//client /* * jsock framework https://github.com/nnpa/jsock open source * Each line should be prefixed with * */ package jsock.tests; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; import java.util.Iterator; import java.util.Scanner; import java.util.logging.Level; import java.util.logging.Logger; import conf.JConfig; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; /** * * @author padaboo I.B Aleksandrov jetananas@yandex.ru */ public class JClientTCPTest { public static void main(String[] args) throws UnknownHostException, IOException, ClassNotFoundException, InterruptedException{ JClientTCPTest tcpTest = new JClientTCPTest(); tcpTest.test(); } public void test(){ Sender sender = new Sender(); sender.start(); Receiver receiver = new Receiver(); receiver.start(); } class Sender extends Thread{ @Override public void run(){ try { InetAddress host = InetAddress.getLocalHost(); Socket socket = null; String message; for(int i=1; i<10;i++){ message = "{\"task\":\"JTestTask\",\"message\":\"test"+i+"\"}"; socket = new Socket(host.getHostName(), JConfig.server_port); //InputStream inStream = socket.getInputStream(); PrintWriter socketOut; socketOut = new PrintWriter(socket.getOutputStream(), true); socketOut.println(message); socket.close(); System.out.println("Send: "+i); Thread.sleep(100); } } catch ( IOException | InterruptedException ex) { Logger.getLogger(JClientTCPTest.class.getName()).log(Level.SEVERE, null, ex); } } } class Receiver extends Thread{ JSONObject jsonObj; JSONParser parser; @Override public void run(){ try { ServerSocket serverSocket = new ServerSocket(JConfig.client_port); String data = ""; while(true){ data = ""; Socket socket = serverSocket.accept(); InputStream inStream = socket.getInputStream(); Scanner scanner = new Scanner(inStream); while(scanner.hasNextLine()){ data += scanner.nextLine(); } System.out.println(data); } } catch (IOException ex) { Logger.getLogger(JClientTCPTest.class.getName()).log(Level.SEVERE, null, ex); } } } }
Сервер
package tasks; import jsock.message.JInMessages; import jsock.message.JOutMessages; import jsock.task.JClientTask; import models.Users; /** * * @author padaboo I.B Aleksandrov jetananas@yandex.ru */ public class JTestTask extends JClientTask{ public JTestTask(JInMessages message) { super(message); } @Override public String[][] rules(){ String[][] rules = { {"require","message"} }; return rules; } @Override public String rights() { //String rigths = "user,admin"; String rigths = "guest"; return rigths; } @Override public void action(){ String message = this.message.json.get("message").toString(); System.out.println(message); String outString = "{\"message\":\"Test\"}"; JOutMessages outMessage = new JOutMessages(this.message.ip,outString); outMessage.insert(); } }
1. Клиента посылает на сервер json строку c названием вызываемой задачи.
2. Задача извлекает переменные из сообщения и посылает ответ.
Задача
Задача должна быть создана в папке tasks и унаследованна от JClientTask.
В конструкторе должна передаваться класс JInMessages с входящим сообщением.
Должны быть реализованы методы rules,rights,action.
в rules описаны правила валидации переменных, можно написать свои правила валидации.
в rights перечисление прав пользователей которые имеют право вызывать действие.
в action основной код.
Извлечение переменных
String message = this.message.json.get("message").toString();
Строка ответа и поставнока в очередь
String outString = "{\"message\":\"Test\"}"; JOutMessages outMessage = new JOutMessages(this.message.ip,outString); outMessage.insert();
Вместо ip можно ставить любой ip который слушает сокет и ждет json строку.
Модели
После установки фремворка по инструкции в базе будут 2 таблицы: Users, Session. Примеры использования есть в папках с задачами.
Все модели должны быть созданы в папке models, унаследованы от DBQuery в котором реализовано подключение к базе данных и основные методы. В классе модели должна быть реализована логика взаимодействия с базой данных.
Права пользователей
1. Права должны быть описаны в задачах в методе rights:guest,user,admin. Неавторизованный пользовател имеет права guest. Зарегистрированнному пользователю присваивается user, эти значения хранятся в базе данных в таблице rights.
Пример: авторизация по токену, модели, права
Получение токена
@Override public void action(){ String email = this.message.json.get("email").toString(); String password = this.message.json.get("password").toString(); Users users = new Users(); boolean isAuth = users.authorization(email,password); String outString; if(isAuth){ String token = users.getToken(); int userId = users.id; String ip = this.message.ip; //System.out.println(insertQuery); Session session = new Session(); session.setToken(userId, token,ip); outString = "{\"token\":\"" + token +"\"}"; }else{ outString = "{\"error\":\"Incorrect login or password \"}"; } JOutMessages outMessage = new JOutMessages(this.message.ip,outString); outMessage.insert(); }
1. В права указываем ожидаемые переменные:email,password.
2. Создаем модель Users, вызываем метод авторизации.
3. Создаем модель сессии — получаем токен.
4. Отправляем ответ.
5. Токен сохраняем на клиенте.
Пример проверки прав
@Override public void action(){ /** * get ip from session and send to open socket **/ System.out.println("user_id: " + webUser.id + " email: " + webUser.email + " rights: "+ webUser.rights); Session session = new Session(); session.findByUserID(12); String ip = session.ip; //all users //session connection String outString = "{\"ip_message\":\"send to user by session id\"}"; JOutMessages outMessage = new JOutMessages(ip,outString); outMessage.insert(); }
1. В правах указываем user.
2. В ожидаемых переменных token
После вызова задачи с токеном и правами «не гость». Пользователь ищется в базе данных в таблице Session, по user_id создается модель Users — которая доступнав задаче в переменной webUser.
Можно отправлять сообщения всем клиентам по user_id в Session или по соединениею в классе JConnections.
Пример регистрации можно посмотреть в классе tasks.JRegistrationTask
Все тесты находятся в папке /tests/.
Более подробные примеры можно посмотреть по ссылкам в начале сообщения.
ссылка на оригинал статьи https://habrahabr.ru/post/318782/
Добавить комментарий