The integration of GatewayWorker and Laravel in the chat room (Part II,

Source: Internet
Author: User

The integration of GatewayWorker and Laravel in the chat room (Part II,
Ideas

The previous article outlines the basic knowledge of GatewayWorker. This article is intended to integrate GatewayWorker to Laravel.

 

GatewayWorker is a server framework based on Socket listening, while Laravel is a Web framework based on the HTTP Request/response model. Therefore, you must understand that the deployment of the two isIndependent,Mutual interference.

Therefore, their physical integration methods are wise. On the official website, author of The GatewayWorker framework provides a combination with the MVC Framework in the manual, as shown in:

 

The client browser establishes a WebSocket connection with GatewayWorker. All business logic is sent to the Web framework by the client through the http get/POST protocol. Only when the client browser needs to actively push data, the Web framework will call the GatewayClient API provided by GatewayWorker, which is actively pushed to the client through WebSocket.

 

Procedure

The general idea is as follows.

First, you need to customize all the processes of GatewayWorker and integrate it into the gatewayworker directory under the root directory of the laravel project. The structure of this directory follows the official recommendation, as shown below:

Gatewayworker/├ ── app │ └ ── chat │ ├ ── Events. php # actual business processing of BusinessWorker processes │ ── start_businessworker.php # Startup file of the BusinessWorker process │ ── start_gateway.php # Startup file of the Gateway process │ ── start_register.php # Startup file of the Register Service ── composer. json ├ ── composer. lock ── start_for_win.bat # Startup File ── start for all Worker processes of GatewayWorker in Windows. php # vendor, the startup file of all Worker processes of GatewayWorker in Linux

The entire gatewayworker/directory structure and source code are almost identical to the official workerman-chat. Only Events. php is slightly different.

Start. php is responsible for starting all worker processes:

// Load all applications/*/start. php to start all services foreach (glob (_ DIR __. '/app/*/start *. php ') as $ start_file) {require_once $ start_file;} // run all services Worker: runAll ();

Start_register.php is responsible for starting the Register process and listening to port 1238 of the local machine, so that the Gateway process can establish communication with the BuisnessWorker process.

$ Register = new Register ('text: // 0.0.0.0: 1238 '); // The text protocol is required.

Start_gateway.php is responsible for starting the Gateway process and listening to client data on port 7272, WebSocket-based connections, and connections. At the same time, set the process name, number of processes, lanIp, start port and heartbeat detection, and register the communication address.

$ Gateway = new Gateway ("Websocket: // 0.0.0.0: 7272"); $ gateway-> name = 'chatgateway'; $ gateway-> count = 4; $ gateway-> lanIp = '000000. 0.0.1 '; // enter the real IP address (not 127.0.0.1) during distributed deployment $ gateway-> startPort = 2300; $ gateway-> pingInterval = 10; // set the heartbeat, prevent route nodes from forcibly disconnecting for a long period of time. $ gateway-> pingData = '{"type": "ping"}'; $ gateway-> registerAddress = '2017. 0.0.1: 1238 '; // used to communicate with the BusinessWorker process, which is consistent with the registration address of the Gateway process.

Start_businessworker.php is responsible for starting the BusinessWorker process, setting the process name, number of processes, and registering the communication address.

$ Worker = new BusinessWorker (); $ worker-> name = 'chatbusinessworker '; $ worker-> count = 4; $ worker-> registerAddress = '2017. 0.0.1: 1238 '; // used to communicate with the Gateway process. It must be consistent with the registered address of the Gateway process.

In Events. php, there are only two tasks:

First, when the client establishes a connection, send the client_id to the client in the onConnect callback (let the client bind the uid and client_id through the AJAX request Web framework ).

Second, when the client connection is closed, use the client_id in the onClose callback to obtain the room_id of the user (the unique ID of the chat room, generated by Laravel) and use Gateway :: sendToGroup ($ group) pushes a customer exit signal to the room (the client receives this signal and initiates an AJAX request to the Web framework to request the latest user list ).

Leave the onMessage callback blank. As mentioned above, all our business logic should be implemented in the Web framework as much as possible. GatewayWorker only provides the Socket service.

Below are some of the Code in Events. php.

Public static function onConnect ($ client_id) {Gateway: sendToClient ($ client_id, json_encode (array ('type' => 'init ', 'client _ id' => $ client_id);} public static function onMessage ($ client_id, $ message) {} public static function onClose ($ client_id) {// room broadcast signal with Connection closed $ room_id = $ _ SESSION ['room _ id']; $ uname = $ _ SESSION ['uname']; if (Gateway:: getClientCountByGroup ($ room_id) {Gateway: sendToGroup ($ room_id, json_encode (array ('type' => 'close ', 'uname' => $ uname )));}}

 

Then, run all the Worker processes to establish internal communication and listen to client connections. Use php start. php start-d to run all Worker processes in the form of daemon.

The following is a WebSocket connection to GatewayWorker on the chat room page.

var ws = new WebSocket("ws://" + document.domain + ":7272");

Note that the websocket Protocol comes from HTML5, which may not be supported by some browsers. You can use the web-socket-js plug-in provided by gimite, which is a WebSocket implemented by Flash.

Then, the ws. onmessage callback receives the client_id from GatewayWorker and sends the POST request to the Laravel Framework Using AJAX to bind the uid to the client_id.

The front-end Websocket receives the client_id and sends the request to bind the uid:

ws.onmessage = function(e) {    var data = JSON.parse(e.data),          type = data.type || '';    switch (type) {        ...        case 'init':            $.post(global_url_bind, {                client_id: data.client_id,                _token: global_csrf_token            }, function(data) {}, 'json');            break;        ...    }}

Code snippets bound to the backend Laravel (using the GatewayClient API ):

// Bind uid and client_id to the room Gateway: bindUid ($ client_id, $ uid); // The uid and room_id have obtained Gateway: joinGroup ($ client_id, $ room_id); // record session (['client _ id' => $ client_id]); // Laravel is responsible for Gateway: setSession ($ client_id, [// GatewayWorker is responsible for 'uid' => $ uid, 'uname' => $ uname, 'Avatar '=> $ avatar, 'bucbble' => $ bubble, 'Room _ id' => $ room_id]);

All subsequent messages in the room will be processed in a unified manner through get/post. The following is the source code of the chat part:

Front end:

$. Post (global_url_say, {type: 'all', // public chat content: content, _ token: global_csrf_token}, function (data) {}, 'json'); $. post (global_url_say, {type: 'to', // Private Chat to_uid: $ ('. to-whom '). children ('span '). attr ('id'), to_uname: $ ('. to-whom '). children ('span '). text (), content: content, _ token: global_csrf_token}, function (data) {}, 'json ');

Backend (Laravel ):

$ Type = $ request-> input ('type ')?: ''; $ Content = htmlspecialchars ($ request-> input ('content'); $ uid = session ('uid '); $ uname = session ('uname'); $ avatar = session ('Avatar'); $ bubble = session ('bucbble '); $ room_id = session ('room _ id'); switch ($ type) {case 'all': // public chat Gateway: sendToGroup ($ room_id, json_encode (['type' => 'all', 'uid' => $ uid, 'uname' => $ uname, 'Avatar '=> $ avatar, 'bucbble' => $ bubble, 'content' => preg_replace ('/^ \ s * @ me/I', '', $ content)]); break; case 'to': // Private Chat $ to_uid = $ request-> input ('to _ uid'); Gateway: sendToUid ($ to_uid, json_encode (['type' => 'to', 'uid' => $ uid, 'uname' => $ uname, 'Avatar '=> $ avatar, 'bucbble' => $ bubble, 'content' => '<a href = "javascript:;"> ws. onmessage = function (e) {var data = JSON. parse (e. data), type = data. type | ''; switch (type ){... case 'close': // notify someone to exit system_policy ('@' + data. uname + 'leaved out. '); // request a new user list $. post (global_url_flush, {room_id: global_room_id, _ token: global_csrf_token}, function (data) {}); break ;...}}

Backend:

$room_id = $request->input('room_id');$sessions = Gateway::getClientSessionsByGroup($room_id);$users_list = [];foreach ($sessions as $client_id => $item) {    $users_list[$item['uid']] = $item['uname'];}$new_message = ['type' => 'flush'];$new_message['users_list'] = $users_list;Gateway::sendToGroup($room_id, json_encode($new_message));

Then the front-end receives the flush message and refreshes the user list:

ws.onmessage = function(e) {    var data = JSON.parse(e.data),        type = data.type || '';        switch (type) {        ...        case 'flush':            flush_users_list(data.users_list);            break;        ...    }}

This is the basic logic of integration. If you are interested in the source code of this chat room, you can find its address below. Thank you for reading.

 

Related Links

Chat-here chat room source code: https://github.com/mingcw/chat-here (these two days a little tight, wait for 25 night I will add its windows version, currently only supports Linux .)

  

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.