NodeJS + Socket.IO ve PHP nasıl entegre edilir?


98

Son zamanlarda nodeJS ve PHP arasında iletişim kurmanın iyi bir yolunu bulmak için etrafa bakıyordum. Fikir şu: nodeJS hala oldukça yenidir ve sadece onunla tam bir uygulama geliştirmek biraz zor olabilir. Dahası, projenizin gerçek zamanlı bildirimler, sohbet gibi yalnızca bir modülü için ihtiyacınız olabilir ... Ve PHP ile diğer tüm şeyleri yönetmek isteyebilirsiniz, çünkü muhtemelen sizin için daha kolaydır (ve avantajlarından yararlanabilirsiniz) CodeIgniter veya Symfony gibi mevcut çerçeveler).

Kolay bir çözüme sahip olmak isterim; Apache ve Node sunucuları arasında iletişim kurmak için cURL veya üçüncü bir sunucu kullanmak istemiyorum. İstediğim şey, istemci tarafında basit Javascript ile düğümden olayları yakalayabilmek.

Tamamlandığında, çoğu zaman istemci tarafının düğüm sunucusu tarafından çalıştığına ve bu nedenle benim durumumda uygulanamayacağına dair herhangi bir yanıt bulamadım. Böylece tüm olası konuları taradım ve sonunda cevabımı buldum; Bunu paylaşmaya ve her şeyin net olduğu bir noktaya sahip olmaya çalışacağım.

Umarım bu bazı insanlara yardımcı olabilir! ;)

Yanıtlar:


131

Bu yüzden, başlangıç ​​olarak, tam koda erişmek istiyorsanız projemi github'a koyuyorum: https://github.com/jdutheil/nodePHP

Çok basit bir örnek proje: bir web sohbeti. Sadece bir yazarınız ve mesajınız var ve gönder düğmesine bastığınızda bir mysql veritabanına kaydedilir. Buradaki fikir, gerçek zamanlı güncellemeler göndermek ve gerçek bir konuşma yapmaktır. ;) Bunun için nodeJS kullanacağız.

PHP kodundan bahsetmeyeceğim, burada gerçekten basit ve ilginç değil; Size göstermek istediğim, nodeJS kodunuzu nasıl entegre edeceğinizdir.

Express ve Socket.IO kullanıyorum, bu yüzden bu modülleri npm ile kurduğunuzdan emin olun. Ardından basit bir nodeJS sunucusu oluşturuyoruz:

var socket = require( 'socket.io' );
var express = require( 'express' );
var http = require( 'http' );

var app = express();
var server = http.createServer( app );

var io = socket.listen( server );

io.sockets.on( 'connection', function( client ) {
    console.log( "New client !" );

    client.on( 'message', function( data ) {
        console.log( 'Message received ' + data.name + ":" + data.message );

        io.sockets.emit( 'message', { name: data.name, message: data.message } );
    });
});

server.listen( 8080 );

Yeni bir kullanıcı bağlandığında olaylarımızı geri aramayı kaydettik; her mesaj aldığımızda (bir sohbet mesajını temsil eder), onu bağlı olan her kullanıcıya yayınlıyoruz. Şimdi, zor kısım: müşteri tarafı! Beni çoğu zaman alan kısım buydu, çünkü nodeServer olmadan Socket.IO kodunu çalıştırabilmek için hangi betiğin olduğunu bilmiyordum (çünkü istemci sayfası Apache tarafından sunulacak).

Ama her şey zaten yapıldı; Socket.IO modülünü npm ile kurduğunuzda, içinde bir betik bulunur /node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.js; benim durumumda PHP sayfamıza ekleyeceğimiz komut dosyası:

    <script src="js/node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.js"></script>
    <script src="js/nodeClient.js"></script>

Ve bitirmek için, nodeClient.js, burada sadece düğüm sunucusuna bağlanıyoruz ve sayfamızı güncellemek için olayın olmasını bekliyoruz. ;)

var socket = io.connect( 'http://localhost:8080' );

$( "#messageForm" ).submit( function() {
    var nameVal = $( "#nameInput" ).val();
    var msg = $( "#messageInput" ).val();

    socket.emit( 'message', { name: nameVal, message: msg } );

    // Ajax call for saving datas
    $.ajax({
        url: "./ajax/insertNewMessage.php",
        type: "POST",
        data: { name: nameVal, message: msg },
        success: function(data) {

        }
    });

    return false;
});

socket.on( 'message', function( data ) {
    var actualContent = $( "#messages" ).html();
    var newMsgContent = '<li> <strong>' + data.name + '</strong> : ' + data.message + '</li>';
    var content = newMsgContent + actualContent;

    $( "#messages" ).html( content );
});

Kodumu mümkün olan en kısa sürede güncellemeye ve iyileştirmeye çalışacağım, ancak bunun şimdiden tüm harika şeylere açık olduğunu düşünüyorum! Bu şeylerle ilgili tavsiye ve incelemelere gerçekten açığım, bunu yapmanın iyi bir yolu mu ..?

Umarım bu bazı insanlara yardımcı olabilir!


18
Bir soru yazdığınızda, "kendi sorunuzu cevaplayın, Soru-Cevap stilini paylaşın" seçeneği vardır, bu yüzden böyle paylaşabileceğimizi düşündüm, eğer yanılıyorsam özür dilerim :)
Jérémy Dutheil

4
Öneri olarak, bu sorunun cevabını burada stackoverflow.com/questions/5818312/mysql-with-node-js birleştirmenin daha üstün bir yöntem olduğunu düşünüyorum. herhangi bir ajax çağrısından kaçınmak ve düğüm kullanımıyla kodu daha satır içi hale getirmek. Artık PHP, basitçe veritabanındaki bilgileri seçebilir.
blackmambo

1
Ana uygulamanızdan farklı bir makinedeyse, düğüm uygulamasının aynı sunucuda olması, ancak farklı bir bağlantı noktası kullanılması yerine io.connect kullanarak düğüm uygulamasına bağlanmak mümkün müdür?
maembe

1
ileti kimlik doğrulaması olarak hmac imzalaması gerektirir. bu sadece php'nin sokete mesaj yayınlayabilmesini sağlar. soket, imzalanmış jetonu inceleyecek ve geçerse, mesajı yayınlayacaktır. bu, istenmeyen postaları önlemek ve veri bütünlüğünü sağlamak için iyidir. bu nedenle istemciden doğrudan düğüm soketine asla göndermeyin. bunun yerine ajax ile php uygulamasına gönderin, ardından bunu soket sunucusuna aktarın. php'den fopen + fwrite veya stream select ile bir websocket sunucusuna bir soket bağlantısı açmak oldukça önemsiz değildir.
r3wt

1
@Bangash ile anlaştık, Verileri PHP yerine mysql db'ye depolamak için Node.js'yi kullanabilirsiniz, bu da onu çok daha hızlı hale getirir
Parthapratim Neog

2

Benim için oldukça iyi çalışan başka bir çözümüm var, ancak (henüz) gerçek sunucuda test etme fırsatım / zamanım olmadığı için birisinin ne kadar etkili olduğu hakkında yorum yapmasını isterim.

İşte node-js kodu. Bu kodu nodeserver.js adlı bir dosyaya koydum:

var http = require('http');

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});

    var knall = new Object();
    knall.totten = "4 tomtar";
    knall.theArr = new Array();
    knall.theArr.push("hoppla")
    knall.theArr.push("hej")
    var strKnall = JSON.stringify(knall);

    res.end(strKnall);
}).listen(process.env.PORT);  

Ve işte php'deki basit kod parçası, file_get_contents () yardımıyla node-js sunucusunu çağırıyor:

$json = file_get_contents('http://localhost:3002/knall.json');
$obj = json_decode($json);

Harika çalışıyor, php sayfasını yüklediğimde, sırayla knall nesnesini jsonify eden nodeserver.js sayfasını çağırıyor.

Windows 10'da iis üzerinde çalışan iki localhost-kurulumum var, bir standart php-server ve nodejs-server düzgün iisnode paketi ile çalışıyor .

'Gerçek' sunucu ubuntu'da çalıştırılır.

Bunun iki sunucu arasındaki iletişim için düzgün ve kolay bir çözüm olduğunu düşünüyorum, ancak birisinin bu konuda herhangi bir yorumu olabilir mi?


Bu bana mantıklı gelmiyor, çünkü düğüm sunucusunu php betiğinin içinden başlatıyorsunuz. Bunun için herhangi bir kullanım durumu düşünemiyorum. İhtiyacımız olan şey, çalışan bir node.js örneği ile php arasında iletişim kurmanın bir yolu.
Lorenz Meyer

@Lorenz yok, bu kendi sunucusunda çalışan node.js betiğidir. Node.js sayfasını doğrudan php'den file_get_contents () ile başka bir php sunucusundan çağırıyorum. Artık günde 500'den fazla kullanıcıyla günlük kullanımda. Belki kafanız karıştı çünkü "localhost: 3002" parçası? Bunun nedeni, bu örneğin, iis'de iki bağımsız sunucu ile yerel Windows bilgisayarımda çalışmasıdır.
Snorvarg

Gerçekten kafam karıştı. Bu, bunun nodejs.jsaslında bir kaynak dosya olmadığı , ancak json? İçerdiği için adlandırdığınız bir URL olduğu anlamına gelir. İlki hiçbir anlam ifade etmiyor, ancak ikincisi bana çok kafa karıştırıcı geliyor.
Lorenz Meyer

@Lorenz, nodejs js dosyasının dosya adını değiştirerek örneği netleştirmeye ve metni biraz düzenlemeye çalıştım. Sorunuzu yanıtlamak için, şimdi nodeserver.js olarak yeniden adlandırılan dosya kendi sunucusunda çalıştırılır. Http.createServer () çağrısı, 80 numaralı bağlantı noktasında gelen bağlantıları dinleyen () bir sunucu oluşturur.
Snorvarg

Node.js sunucusunu doğrudan bir tarayıcıdan, sadece " localhost: 3002 / nodeserver.js " url'sini girerek çağırabileceğinizi ve bir json yanıtı alacağınızı unutmayın. Php dosyasındaki file_get_contents (), içeriği başka bir sunucudan, bu durumda node.js sunucusundan alır.
Snorvarg

0

Benzerini deneyin veya nodejs'deki eksiksiz örnek kod için blogumu kontrol edebilirsiniz


Sayfanızın tarafında:

  • Yük Soketi JS

https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js

  • Soketin nesnesini yapın

var soket = io ();

  • emitVerileri düğüm sunucusuna göndermek için işlevi kullanın .

socket.emit ('yeni_notification', {
mesaj: 'mesaj',
başlık: 'başlık',
simge: 'simge',
});

Şimdi kodunuz şöyle görünecek

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script>

var socket = io(); 

$(document).ready(function($) {
  $('.rules-table').on('click', '.runRule', function(event) {
    event.preventDefault();
    /* Act on the event */
    var ruleID = $(this).parents('tr').attr('id');

    // send notification before going to post 
    socket.emit('new_notification', {
        message: 'Messge is ready to sent',
        title: title,
        icon: icon,
    });
    $.ajax({
      url: '/ajax/run-rule.php',
      type: 'POST',
      dataType: 'json',
      data: {
        ruleID: ruleID
      },
    })
    .done(function(data) {
      console.log(data);

      // send notification when post success 
      socket.emit('new_notification', {
        message: 'Messge was sent',
        title: title,
        icon: icon,
      });

    })
    .fail(function() {
      console.log("error");

      // send notification when post failed 
      socket.emit('new_notification', {
        message: 'Messge was failed',
        title: title,
        icon: icon,
      });
    })
    .always(function() {
      console.log("complete");
    });

  });
});

Şimdi Node sunucusu tarafında, isteğinizi alma ve tüm bağlı cihazlara / tarayıcılara (server.js) bir mesaj gönderme isteğiniz için işleyici yapın

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res) {
   res.sendfile('index.html');
});


io.on('connection', function (socket) {
  socket.on( 'new_notification', function( data ) {
    console.log(data.title,data.message);

    // Now Emit this message to all connected devices
    io.sockets.emit( 'show_notification', { 
      title: data.title, 
      message: data.message, 
      icon: data.icon, 
    });
  });
});

http.listen(3000, function() {
   console.log('listening on localhost:3000');
});

Artık istemci / tarayıcı / istemci tarafı, düğüm sunucusundan soket mesajını almak için bir alıcı yapar

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script>   

var socket = io();

/**
 * Set Default Socket For Show Notification
 * @param {type} data
 * @returns {undefined}
 */
socket.on('show_notification', function (data) {
    showDesktopNotification(data.title, data.message, data.icon);
});
/**
 * Set Notification Request
 * @type type
 */
function setNotification() {
    showDesktopNotification('Lokesh', 'Desktop Notification..!', '/index.jpeg');
    sendNodeNotification('Lokesh', 'Browser Notification..!', '/index.jpeg');
}
/**
 * Check Browser Notification Permission
 * @type window.Notification|Window.Notification|window.webkitNotification|Window.webkitNotification|Window.mozNotification|window.mozNotification
 */
var Notification = window.Notification || window.mozNotification || window.webkitNotification;
Notification.requestPermission(function (permission) {
});
/**
 * Request Browser Notification Permission 
 * @type Arguments
 */
function requestNotificationPermissions() {
    if (Notification.permission !== 'denied') {
        Notification.requestPermission(function (permission) {
        });
    }
}
/**
 * Show Desktop Notification If Notification Allow
 * @param {type} title
 * @param {type} message
 * @param {type} icon
 * @returns {undefined}
 */
function showDesktopNotification(message, body, icon, sound, timeout) {
    if (!timeout) {
        timeout = 4000;
    }
    requestNotificationPermissions();
    var instance = new Notification(
            message, {
                body: body,
                icon: icon,
                sound: sound
            }
    );
    instance.onclick = function () {
        // Something to do
    };
    instance.onerror = function () {
        // Something to do
    };
    instance.onshow = function () {
        // Something to do
    };
    instance.onclose = function () {
        // Something to do
    };
    if (sound)
    {
        instance.sound;
    }
    setTimeout(instance.close.bind(instance), timeout);
    return false;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.