nodeJS + Socket.IO와 PHP를 통합하는 방법은 무엇입니까?


98

나는 최근에 nodeJS와 PHP 사이에 통신하는 좋은 방법을 찾기 위해 둘러 보았습니다. 여기에 아이디어가 있습니다. nodeJS는 여전히 새롭고 그것만으로 전체 애플리케이션을 개발하는 것은 다소 까다로울 수 있습니다. 또한 실시간 알림, 채팅 등 프로젝트의 한 모듈에만 필요할 수 있습니다. 그리고 PHP로 다른 모든 항목을 관리하고 싶을 수 있습니다. CodeIgniter 또는 Symfony와 같은 기존 프레임 워크).

나는 쉬운 해결책을 갖고 싶다. Apache와 Node 서버간에 통신하기 위해 cURL 또는 세 번째 서버를 사용하고 싶지 않습니다. 내가 원하는 것은 클라이언트 측의 간단한 Javascript에서 노드에서 이벤트를 잡을 수 있다는 것입니다.

나는 완전한 곳에서 대부분의 경우 클라이언트 측이 노드 서버에 의해 실행되어 제 경우에는 적용되지 않는다는 답을 찾지 못했습니다. 그래서 가능한 모든 주제를 탐색하고 마침내 내 답을 찾았습니다. 나는 이것을 공유하고 그것이 모두 명확한 지점을 가지려고 노력할 것입니다.

이것이 어떤 사람들을 도울 수 있기를 바랍니다! ;)

답변:


131

먼저 전체 코드에 액세스하려면 https://github.com/jdutheil/nodePHP 에서 내 프로젝트를 github에 넣습니다.

매우 간단한 예제 프로젝트 인 웹 채팅입니다. 작성자와 메시지 만 있고 send를 누르면 mysql 데이터베이스에 저장됩니다. 아이디어는 실시간 업데이트를 보내고 실제 대화를 나누는 것입니다. ;) 우리는이를 위해 nodeJS를 사용할 것입니다.

PHP 코드에 대해서는 이야기하지 않겠습니다. 여기서는 정말 간단하고 흥미롭지 않습니다. 제가 보여 드리고 싶은 것은 nodeJS 코드를 통합하는 방법입니다.

나는 express와 Socket.IO를 사용하므로 npm으로 해당 모듈을 설치하십시오. 그런 다음 간단한 nodeJS 서버를 만듭니다.

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 );

새 사용자가 연결될 때 이벤트 콜백을 등록했습니다. 메시지 (채팅 메시지를 나타냄)를받을 때마다 연결된 모든 사용자에게 브로드 캐스트합니다. 이제 까다로운 부분 : 클라이언트 측! (클라이언트 페이지가 Apache에서 제공되기 때문에) nodeServer없이 Socket.IO 코드를 실행할 수있는 스크립트가 무엇인지 몰랐기 때문에 대부분의 시간을 소요했습니다.

그러나 모든 것이 이미 완료되었습니다. npm으로 Socket.IO 모듈을 설치할 때 스크립트는 /node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.js; 필자의 경우 PHP 페이지에 포함 할 스크립트는 다음과 같습니다.

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

완료하려면 nodeClient.js에서 노드 서버에 연결하고 이벤트가 페이지를 업데이트 할 때까지 기다립니다. ;)

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 );
});

가능한 한 빨리 코드를 업데이트하고 개선하려고 노력할 것입니다.하지만 이미 모든 멋진 기능에 열려 있다고 생각합니다! 나는이 일에 대한 조언과 리뷰를 정말 열려 있습니다. 그렇게하는 것이 좋은 방법입니까, ..?

이것이 어떤 사람들을 도울 수 있기를 바랍니다!


18
당신이 질문을 쓸 때 우리가 같이 공유 할 수 있습니다 생각 때문에 음, 옵션 "자신의 질문에 대답, 지식을 공유 Q & A 스타일은"미안 해요 :) 틀렸다면,이
제레미 Dutheil

4
제안으로, 여기에이 질문에 대한 답변을 통합하는 것이 더 나은 방법 이라고 생각합니다. stackoverflow.com/questions/5818312/mysql-with-node-js . ajax 호출을 피하고 노드를 사용하여 코드를 더 인라인으로 만듭니다. 이제 PHP는 데이터베이스에서 정보를 간단히 선택할 수 있습니다.
blackmambo 2013

1
노드 앱이 동일한 서버에 있지만 다른 포트를 사용하는 대신 기본 앱과 다른 시스템에있는 경우 io.connect를 사용하여 노드 앱에 연결할 수 있습니까?
maembe

1
메시지 인증으로 hmac 서명이 필요합니다. 이것은 오직 php만이 소켓에 메시지를 브로드 캐스트 할 수 있도록합니다. 소켓은 서명 된 토큰을 검사하고 통과하면 ti는 메시지를 브로드 캐스트합니다. 이는 스팸을 방지하고 데이터 무결성을 보장하는 데 유용합니다. 따라서 클라이언트에서 노드 소켓에 직접 게시하지 마십시오. 대신 ajax를 사용하여 PHP 앱에 게시 한 다음 소켓 서버에 전달하십시오. fopen + fwrite 또는 php에서 스트림 선택을 사용하여 websocket 서버에 대한 소켓 연결을 여는 것은 매우 간단합니다.
r3wt

1
@Bangash로 합의, 당신은 대신 PHP의 MySQL의 DB에 데이터를 저장하기 위해 Node.js를 사용할 수 있습니다, 그것은 그것을 훨씬 더 빨리 만들 것
Parthapratim Neog

2

저에게 아주 잘 작동하는 또 다른 솔루션이 있지만 실제 서버에서 테스트 할 기회 / 시간이 아직 없었기 때문에 누군가가 얼마나 효과적인 지에 대해 언급 해 주었으면합니다.

여기에 node-js 코드가 있습니다. 이 코드를 nodeserver.js라는 파일에 넣었습니다.

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);  

다음은 file_get_contents ()의 도움으로 node-js 서버를 호출하는 PHP의 간단한 코드입니다.

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

훌륭하게 작동합니다. php-page를로드하면 knall-object를 jsonify하는 nodeserver.js 페이지를 차례로 호출합니다.

Windows 10의 iis에서 실행되는 두 개의 localhost-installations, 하나의 표준 php-server가 있으며 nodejs-server는 깔끔한 iisnode 패키지 와 함께 작동 합니다.

'실제'서버는 우분투에서 실행됩니다.

두 서버 간의 통신을위한 깔끔하고 쉬운 솔루션이라고 생각하지만 누군가 이에 대해 의견이 있으십니까?


PHP 스크립트 내에서 노드 서버를 시작하기 때문에 이것은 나에게 의미가 없습니다. 나는 이것에 대한 사용 사례를 상상할 수 없습니다. 우리에게 필요한 것은 실행중인 node.js 인스턴스와 php간에 통신하는 방법입니다.
Lorenz Meyer

@Lorenz, 즉 node.js 스크립트는 자체 서버에서 실행되지 않습니다. 다른 php-server에서 file_get_contents ()를 사용하여 PHP에서 직접 node.js-page를 호출하고 있습니다. 이제 매일 500 명 이상의 사용자가 매일 사용하고 있습니다. "localhost : 3002"조각 때문에 혼란 스러울 수 있습니까? 이 예제는 iis에 두 개의 독립 실행 형 서버가있는 내 로컬 Windows 컴퓨터에서 실행되기 때문입니다.
Snorvarg

정말 혼란 스러워요. 이 수단 nodejs.js실제로 없는 소스 파일하지만 JSON이 포함되어 있기 때문에 그것은 당신이, 그래서 URL 이름은? 첫 번째는 의미가 없지만 후자는 나에게 매우 혼란스러워 보입니다.
Lorenz Meyer

@Lorenz, nodejs js 파일의 파일 이름을 변경하여 예제를 명확히하고 텍스트를 약간 편집하려고했습니다. 질문에 답하기 위해 이제 nodeserver.js로 이름이 변경된 파일이 자체 서버에서 실행됩니다. http.createServer () 호출은 포트 80에서 들어오는 연결을 수신하는 서버를 생성합니다.
Snorvarg

url " localhost : 3002 / nodeserver.js "를 입력하기 만하면 브라우저에서 직접 node.js 서버를 호출 할 수 있습니다 . 그러면 json-response가 표시됩니다. php 파일의 file_get_contents ()는 다른 서버 (이 경우 node.js 서버)에서 콘텐츠를 가져옵니다.
Snorvarg

0

유사하게 시도하거나 내 블로그 에서 nodejs의 전체 샘플 코드를 확인할 수 있습니다.


페이지 쪽에서 :

  • 소켓 JS로드

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

  • 소켓의 개체 만들기

var socket = io ();

  • emit함수를 사용하여 데이터를 nodeserver로 보냅니다.

socket.emit ( 'new_notification', {
메시지 : '메시지',
제목 : '제목',
아이콘 : '아이콘',
});

이제 코드는 다음과 같습니다.

<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");
    });

  });
});

이제 노드 서버 측에서 요청을 받고 연결된 모든 장치 / 브라우저 (server.js)에 메시지를 보내기위한 처리기를 만듭니다.

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');
});

이제 클라이언트 / 브라우저 / 클라이언트 측은 노드 서버에서 소켓 메시지를 수신하도록 수신자를 만듭니다.

<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;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.