Когда обрабатывать уведомления Socket.io? - PullRequest
0 голосов
/ 26 сентября 2018

Я разрабатываю социальное приложение для IOS, написанное на SWIFT.

. Бэкэнд - PHP, MySQL (для обработки событий), + немного NodeJS, Socket.io (для чата в реальном времени и уведомлений).


Я успешно создал чат:

Когда пользователь отправляет сообщение, сервер Socket.io обрабатывает его следующим образом:

  • вставляетданные в базу данных
  • в случае успеха отправляют сообщение всем участникам-участникам

/, поэтому для этого бэкэнд является только сервером Socket.io, который обрабатываетбаза данных также


Работает нормально.

Но есть события, которые не предназначены для работы в реальном времени, но все же я хочу отправить уведомление данному пользователюнапример, с помощью Socket.io

: если публикация понравилась, отправьте уведомление владельцу сообщения

Я уже написал PHP-файлы для сохранениякак в базе данных, но

Как мне сделать notiЧасть, безопасная?


У меня есть 3 идеи:

  1. Приложение отправляет веб-запросмой бэкэнд PHP + MySQL, он обрабатывает данные там, а затем, вернув «успех», приложение (SWIFT) отправляет уведомление владельцу поста (через модуль Socket.io XCode)
func likePost(postId : Int, completion: @escaping (ActionResult?)->()){

        let connectUrl = URL(string: appSettings.url + "/src/main/like.php")
        var request = URLRequest(url: connectUrl!)
        request.httpMethod = "POST"
        let postString = "userId=\(userId)&session=\(session)&pId=\(postId)"
        request.httpBody = postString.data(using: String.Encoding.utf8)


        let task = URLSession.shared.dataTask(with: request) {
            (data: Data?, response: URLResponse?, error: Error?) in

            if error != nil {
                return completion(ActionResult(type: 0, code: 0, title: "error", message: "something went wrong"))
            }
            do {

                let responseJson = try JSONSerialization.jsonObject(with: data!, options: [])
                if let responseArray = responseJson as? [String: Any] {

                    let responseStatus = responseArray["status"] as? String
                    let responseTitle = responseArray["title"] as? String
                    let responseMessage = responseArray["message"] as? String


                    if responseStatus != "1" {
                        return completion(ActionResult(type: 0, code: 0, title: "error", message: "something went wrong"))
                    }

                    // SUCCESS, SEND NOTI WITH SOCKET.IO

                    socket.emit("notification_likedPost", ["postId": postId)

                    return completion(ActionResult(type: 1, title: "success", message: "yay"))

                }
            } catch {
                return completion(ActionResult(type: 0, code: 0, title: "error", message: "something went wrong"))
            }
        }
        task.resume()
    }
то же самое, но после возврата «успеха» из PHP, сам (файл PHP) обрабатывает также отправку уведомлений Socket.IO (я думаю, что это невозможно, я не нашеллюбые плагины PHP-> Socket.io ..)

-

Приложение ничего не отправляет в мой веб-файл PHP + MySQL, вместо этого оно отправляет весь процесс «как» на мой сервер NodeJs, Socket.IO, обрабатывает его там, сохраняет в базе данных, затем отправляет уведомления (точно так же, как часть чата в реальном времени, но это было бы много работы, потому что я уже написал весь другой код в файлах PHP)

Первый случай - самый идеальный для меня , но я боюсь, что он будет взломан ..

Потому что, если я сделаю это первым способом, бэкэндСервер NodeJs + Socket.io не будет проверять, был ли процесс привязанности успешным (потому что он был проверен на стороне клиента)

, так что вполне вероятно, что любой мог отправить ложные уведомления типа "пост", как миллиард раз.


Тогда, возможно, второй вариант тоже подойдет, так что бэкэнд обрабатывает и проверку, и отправку уведомлений, , но, к сожалению, нет плагина Socket.io для PHP

Ответы [ 3 ]

0 голосов
/ 03 октября 2018

Вы можете создать несколько каналов веб-сокетов.В вашем случае вы добавили один, используя socket.io в NodeJS.Вы можете добавить другой канал через php way.

Вы можете слушать этот канал так же, как слушаете с NodeJS.

Несколько удобных ссылок 1. http://php.net/manual/en/book.sockets.php 2. Как создать сервер веб-сокетов на PHP

0 голосов
/ 04 октября 2018

Я понимаю ваше беспокойство, поскольку весь ваш проект имеет большую концентрацию PHP-кода по сравнению с другими фреймворками / языками.Чтобы исправить вашу проблему, вот реализация Socket.io для PHP v5.3 и выше https://github.com/walkor/phpsocket.io.

С помощью этого вы можете использовать библиотеку socket.io в своем PHP-коде.Ниже вы можете увидеть пример использования библиотеки Socket.io в PHP.

use Workerman\Worker;
use PHPSocketIO\SocketIO;

// listen port 2020 for socket.io client
$io = new SocketIO(2020);
$io->on('connection', function($socket){
    $socket->addedUser = false;
    // when the client emits 'new message', this listens and executes
    $socket->on('new message', function ($data)use($socket){
        // we tell the client to execute 'new message'
        $socket->broadcast->emit('new message', array(
            'username'=> $socket->username,
            'message'=> $data
        ));
    });
    // when the client emits 'add user', this listens and executes
    $socket->on('add user', function ($username) use($socket){
        global $usernames, $numUsers;
        // we store the username in the socket session for this client
        $socket->username = $username;
        // add the client's username to the global list
        $usernames[$username] = $username;
        ++$numUsers;
        $socket->addedUser = true;
        $socket->emit('login', array( 
            'numUsers' => $numUsers
        ));
        // echo globally (all clients) that a person has connected
        $socket->broadcast->emit('user joined', array(
            'username' => $socket->username,
            'numUsers' => $numUsers
        ));
    });
    // when the client emits 'typing', we broadcast it to others
    $socket->on('typing', function () use($socket) {
        $socket->broadcast->emit('typing', array(
            'username' => $socket->username
        ));
    });
    // when the client emits 'stop typing', we broadcast it to others
    $socket->on('stop typing', function () use($socket) {
        $socket->broadcast->emit('stop typing', array(
            'username' => $socket->username
        ));
    });
    // when the user disconnects.. perform this
    $socket->on('disconnect', function () use($socket) {
        global $usernames, $numUsers;
        // remove the username from global usernames list
        if($socket->addedUser) {
            unset($usernames[$socket->username]);
            --$numUsers;
           // echo globally that this client has left
           $socket->broadcast->emit('user left', array(
               'username' => $socket->username,
               'numUsers' => $numUsers
            ));
        }
   });
});

Worker::runAll();
0 голосов
/ 28 сентября 2018

Было бы намного проще ...

Забудьте PHP, наберите полный Nodejs:

Экспресс (вы также можете комбинировать его с рулями) & i18n для многоязычных целей)

С помощью Express вы можете создать маршрутизатор для входящих запросов (GET, PUT, POST ,...)

Это означает, что вы можете использовать его для рендеринга страниц с динамическими данными на стороне сервера

const express = require('express');
const exphbs = require('express-handlebars');
const app = express();

// Register Handlebars view engine
app.engine('handlebars', exphbs());
// Use Handlebars view engine
app.set('view engine', 'handlebars');

var visit_counter = 0; 
app.get('/', (req, res) => {
  var time_stamp = Date.now(); visit_counter++
  res.render('index',{"timestamp":time_stamp,"visits":visit_counter});
});

app.listen(3000, () => {
  console.log('Example app is running → PORT 3000');
});

Файл views/index.hbs будет выглядеть следующим образом:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Example App</title>
</head>
<body>

 <p> Current Time : {{timestamp}} </p>
 <p> Total Visits : {{visits}} </p>

</body>
</html>

Эта часть выше представляет собой пример серверных данных, отображаемых в окончательном HTML.


Socket.io (если вы хотите более 1 экземпляраработающего сервера, нет проблем, поиск socket.io-redis )

Вы можете комбинировать express с socket.io по-разному, вы даже можете использовать аутентификацию на основе файлов cookie для вашего сокетапротокол.поэтому, когда приходит событие, вы можете сказать 100%, является ли он законным пользователем и его идентификатором пользователя.


Чтобы предотвратить спам лайков ... вы должны каким-то образом контролировать их.Вы должны сохранить действие подобного, чтобы оно не могло повторяться более одного раза для одного и того же сообщения (поэтому здесь важными переменными кажутся идентификатор пользователя и идентификатор сообщения)



А вот и обновление:

Поскольку вы совершенно ясно дали понять, что вам нужен комбо php & nodejs :

Redis являетсяхранилище структуры данных памяти, которое можно использовать в качестве базы данных, кэша и брокера сообщений.

PHPRedis @ Github

Redis PubSub сPHP и Node.JS

Быстрый пример чтения Node.js PHP-сессии на Redis

Используя Redis, вы можете легко прослушивать события php из вашегоЭкземпляр nodejs.

Я предлагаю вам также подумать о будущем масштабировании вашей системы и попробовать узнать больше nodejs, чтобы иметь возможность перейти от php.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...