Всем доброго времени суток. Разрабатываю онлайн 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
> jsock.doc
Пример отправки и приема сообщений
Клиент:
Сервер:
1. Клиента посылает на сервер json строку c названием вызываемой задачи.
2. Задача извлекает переменные из сообщения и посылает ответ.
Задача
Задача должна быть создана в папке tasks и унаследованна от JClientTask. В конструкторе должна передаваться класс JInMessages с входящим сообщением. Должны быть реализованы методы rules,rights,action. В rules описаны правила валидации переменных, можно написать свои правила валидации. В rights перечисление прав пользователей которые имеют право вызывать действие.
в action основной код.
Извлечение переменных
Строка ответа и поставнока в очередь
Вместо ip можно ставить любой ip который слушает сокет и ждет json строку.
Модели
После установки фремворка по инструкции в базе будут 2 таблицы: Users, Session. Примеры использования есть в папках с задачами.
Все модели должны быть созданы в папке models, унаследованы от DBQuery в котором реализовано подключение к базе данных и основные методы. В классе модели должна быть реализована логика взаимодействия с базой данных.
Права пользователей
1. Права должны быть описаны в задачах в методе rights:guest,user,admin. Неавторизованный пользовател имеет права guest. Зарегистрированнному пользователю присваивается user, эти значения хранятся в базе данных в таблице rights.
Пример: авторизация по токену, модели, права
Получение токена
1. В права указываем ожидаемые переменные:email,password.
2. Создаем модель Users, вызываем метод авторизации.
3. Создаем модель сессии — получаем токен.
4. Отправляем ответ.
5. Токен сохраняем на клиенте.
Пример проверки прав
1. В правах указываем user.
2. В ожидаемых переменных token
После вызова задачи с токеном и правами «не гость». Пользователь ищется в базе данных в таблице Session, по user_id создается модель Users — которая доступнав задаче в переменной webUser.
Можно отправлять сообщения всем клиентам по user_id в Session или по соединениею в классе JConnections.
Пример регистрации можно посмотреть в классе tasks.JRegistrationTask. Все тесты находятся в папке /tests/. Более подробные примеры можно посмотреть по ссылкам в начале сообщения.
Где может пригодится:
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
> jsock.doc
Пример отправки и приема сообщений
Клиент:
//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/. Более подробные примеры можно посмотреть по ссылкам в начале сообщения.
Поделиться с друзьями
Комментарии (10)
tigraboris
30.12.2016 17:50Да да ад… именно так все онлайн игры и работают.
Padaboo
30.12.2016 17:51Я смотрел много реализаций. Тут можно привязку к играм не делать — многопоточный асинхронный сервер.
Yag0andy2006
31.12.2016 23:03Akka
Padaboo
01.01.2017 21:12Akka- http?
Мне нужен tcp/udpYag0andy2006
02.01.2017 13:42http://doc.akka.io/docs/akka/snapshot/scala/io-tcp.html
http://doc.akka.io/docs/akka/current/scala/io-udp.html
laphroaig
Иван, а вы пробовали свои предыдущие статьи перечитывать и комментарии к ним, чтобы хотя-бы ограниченно понять, почему они все без исключения в минус уходят? Упорство и труд все перетрут, но не в данном случае, когда есть упорство, но нет труда
Padaboo
Может быть я не мастер выражаться и оформлять текст, но постарался передать мысль макимальном емко, понятно и без лишних слов. Работает нормально.
laphroaig
ok