1, PHP7 installing the spool extension
PHP swoole extension download address
Github: https://github.com/swoole/swoole-src/tags
PHP official extension library: http://pecl.php.net/package/swoole
Open source China: http://git.oschina.net/swoole/swoole/tags
1. Custom installation
#Download wget https://pecl.php.net/get/swoole-4.3.3.tgz #Unzip tar zxf swoole-4.3.3 Tgz # compile and install extension # enter the directory cd swoole-4.3.3 # execute phpize command to generate the configure executable # if you don't know where the phpize path is, you can use which phpize to view the corresponding path / usr/bin/phpize # for configuration. If you don't know where the PHP config path is, you can use which PHP config to view the corresponding path/ Configure -- with PHP config = / usr / bin / PHP config # compile and install make & & make install VI / etc / PHP Ini copy the following code: extension = swoole So can be put into the file you opened or created without restarting any service # to check whether the extension is successfully installed PHP - m|grep spool
2. Install PHP spoole extension on pagoda panel
If you feel that the above installation is complex, you can use the pagoda panel to realize one click installation

2, Configure nginx reverse proxy
1. Connect to a remote alicloud server using xshell
2. Use the command (find / -name nginx.conf) to find nginx Configuration file where conf is located

3. Use the command (vim /etc/nginx/nginx.conf) to find and enter the vim editor


View the configuration file information that can be imported under / etc/nginx/conf.d /
4. Use the command (cd /etc/nginx/conf.d /) to enter the path and create a new configuration file: study lishuo. net. conf

5. Configure nginx reverse proxy to access study lishuo. Net domain name forwarding port number to 127.0.0.1:9511, that is, the port number forwarded to websocket
copy# The name of study, the rule of reverse proxy, can be used casually upstream study{ server 127.0.0.1:9511; } server { listen 80; server_name study.lishuo.net; error_page 404 /404.html; location = /404.html { } location / { index index.php index.html index.htm; if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s=/$1 last; } #wss configuration client_max_body_size 100m; proxy_redirect off; proxy_set_header Host $host;# http requested host domain name proxy_set_header X-Real-IP $remote_addr;# Remote real IP address proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;#IP address before forwarding after reverse proxy proxy_read_timeout 604800s;#The heartbeat time of websocket is 60s by default proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_pass http://study; } error_page 500 502 503 504 /50x.html; location = /50x.html { } #Add the following information to configure Nginx to process your PHP requests through fastcgi. location ~ .php$ { fastcgi_pass 127.0.0.1:9001; #Forward PHP requests to the native FPM through php-9000. fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; #Nginx calls the fastcgi interface to process PHP requests. } }
3, Wechat applet socket legal domain name configuration
1. Log in to wechat open platform https://mp.weixin.qq.com/
2. Development = > development management = > development settings, complete legal domain name settings

3. Now that the configuration has been completed, the next step is to realize the function, wechat applet + PHP code
4, Effect demonstration and code

1. Applet side code
Path of applet page code / pages / contact / contact wxml
copy<!--pages/contact/contact.wxml--> <view> <scroll-view scroll-y scroll-into-view='{{toView}}' style='height: {{scrollHeight}};'> <!-- <view class='scrollMsg'> --> <block wx:key wx:for='{{msgList}}' wx:for-index="index"> <!-- Single message 1 sent by customer service (left) --> <view wx:if='{{item.speaker=="server"}}' id='msg-{{index}}' style='display: flex; padding: 2vw 11vw 2vw 2vw;'> <view style='width: 11vw; height: 11vw;'> <image style='width: 11vw; height: 11vw; border-radius: 10rpx;' src='https://cdn.pixabay.com/photo/2020/02/10/12/47/girl-4836394__340.jpg'></image> </view> <view style='width: 4vw; height: 11vw; margin-left: 0.5vw; display: flex; align-items: center; z-index: 9;'> <view class="triangle_border_left"></view> </view> <view class='leftMsg'>{{item.content}}</view> </view> <!-- Single message 2 sent by user (right) --> <view wx:else id='msg-{{index}}' style='display: flex; justify-content: flex-end; padding: 2vw 2vw 2vw 11vw;'> <view class='rightMsg'>{{item.content}}</view> <view style='width: 4vw; height: 11vw; margin-right: 0.5vw; display: flex; align-items: center; z-index: 9;'> <view class="triangle_border_right"></view> </view> <view style='width: 11vw; height: 11vw;'> <image style='width: 11vw; height: 11vw; border-radius: 10rpx;' src='https://cdn.pixabay.com/photo/2021/09/24/10/00/chick-6652163__340.jpg'></image> </view> </view> </block> <!-- </view> --> <!-- seize a seat --> <view style='width: 100%; height: 18vw;'></view> </scroll-view> <view class='inputRoom' style='bottom: {{inputBottom}}'> <image style='width: 7vw; margin-left: 3.2vw;' src='https://img95.699pic.com/element/40030/6429.png_300.png' mode='widthFix'></image> <input bindconfirm='sendClick' adjust-position='{{false}}' value='{{inputVal}}' confirm-type='send' bindfocus='focus' bindblur='blur'></input> </view> </view>
2. Path of applet page style code / pages / contact / contact wxss
copy/* pages/contact/contact.wxss */ page { background-color: #f1f1f1; } .inputRoom { width: 100vw; height: 16vw; border-top: 1px solid #cdcdcd; background-color: #f1f1f1; position: fixed; bottom: 0; display: flex; align-items: center; z-index: 20; } input { width: 76vw; height: 9.33vw; background-color: #fff; border-radius: 40rpx; margin-left: 2vw; padding: 0 3vw; font-size: 28rpx; color: #444; } .leftMsg { font-size: 35rpx; color: #444; line-height: 7vw; padding: 2vw 2.5vw; background-color: #fff; margin-left: -1.6vw; border-radius: 10rpx; z-index: 10; } .rightMsg { font-size: 35rpx; color: #444; line-height: 7vw; padding: 2vw 2.5vw; background-color: #96EB6A; margin-right: -1.6vw; border-radius: 10rpx; z-index: 10; } /*towards the left*/ .triangle_border_left { width: 0; height: 0; border-width: 10px 30px 30px 0; border-style: solid; border-color: transparent #fff transparent transparent; /*Transparent yellow transparent */ margin: 40px auto; position: relative; } /*towards the right*/ .triangle_border_right { width: 0; height: 0; border-width: 0px 30px 20px 13px; border-style: solid; border-color: transparent transparent transparent #96EB6A; /*Transparent yellow*/ margin: 40px auto; position: relative; }
Path of applet configuration file code / pages / contact / contact json
copy{ "navigationBarTitleText":"Ke Zuo customer service", "usingComponents": { } }
Path of applet business logic code / pages / contact / contact js
copy// pages/contact/contact.js const app = getApp(); var inputVal = ''; var msgList = []; var windowWidth = wx.getSystemInfoSync().windowWidth; var windowHeight = wx.getSystemInfoSync().windowHeight; var keyHeight = 0; /** * Initialization data */ function initData(that) { //Contents of input box inputVal = ''; //Message list, including chat content between customer service and users msgList = [{ speaker: 'server', contentType: 'text', content: 'Hiļ¼Dear little Lord, I finally wait for you! Welcome to Kezuo store. It's my pleasure to serve you.' }, { speaker: 'customer', contentType: 'text', content: 'It's too early for you to be happy' } ] that.setData({ msgList, inputVal }) } Page({ /** * Initial data of the page */ data: { scrollHeight: '100vh', inputBottom: 0 }, /** * Life cycle function -- listening for page loading */ onLoad: function(options) { //Initialize websocket connection this.chat(); //Method of monitoring heartbeat this.webSocketXin(); //Chat method initData(this); //Listen for messages wx.onSocketMessage(res=>{ //Append to message list msgList.push(JSON.parse(res.data)) inputVal = ''; this.setData({ msgList, inputVal }); }) }, //Page unload time onUnload(){ wx.closeSocket(); }, /** * Get focus */ focus: function(e) { keyHeight = e.detail.height; this.setData({ scrollHeight: (windowHeight - keyHeight) + 'px' }); this.setData({ toView: 'msg-' + (msgList.length - 1), inputBottom: keyHeight + 'px' }) //Calculate msg height // calScrollHeight(this, keyHeight); }, //Lose focus (soft keyboard disappears) blur: function(e) { this.setData({ scrollHeight: '100vh', inputBottom: 0 }) this.setData({ toView: 'msg-' + (msgList.length - 1) }) }, /** * Send click monitor */ sendClick: function(e) { //Information sent by customers let customerMsg = { uid: 10, speaker: 'customer', contentType: 'text', content: e.detail.value }; //Turn off heartbeat packet this.webSocketXin(60000, false) //Send to websocket wx.sendSocketMessage({ data: JSON.stringify(customerMsg), success:res=>{ //Restart heartbeat packet this.webSocketXin(40000, true) } }) //Append to message list msgList.push(customerMsg) inputVal = ''; this.setData({ msgList, inputVal }); }, /** * Back to previous page */ toBackClick: function() { wx.navigateBack({}) }, /** * websocket */ chat(){ //socket for connecting php wx.connectSocket({ //wss protocol is equivalent to having an ssl certificate, https //ws is equivalent to http, which is not a practical certificate url: 'ws://study.lishuo.net', success: function () { console.log('websocket Connection successful~') }, fail: function () { console.log('websocket connection failed~') } }) }, /** * Method for monitoring websocket heartbeat connection */ webSocketXin(time=60000,status=true){ var timing; if(status == true){ timing = setInterval(function () { console.log("The current heartbeat has been reconnected"); //Loop execution code wx.sendSocketMessage({ data: JSON.stringify({ type: 'active' }), fail(res) { //Close connection wx.closeSocket(); //Tips wx.showToast({ title: 'The current chat has been disconnected', icon:'none' }) clearInterval(timing); console.log("Current heartbeat is off"); } }); }, time) //The cycle time should not exceed 1 minute } else { //off timer clearInterval(timing); console.log("Current heartbeat is off"); } } })
2. Server code (PHP code)
wechat_websocket.php
copy<?php //Create a WebSocket Server object and listen on port 0.0.0.0:9502 $ws = new Swoole\WebSocket\Server('0.0.0.0', 9511); //Listen for WebSocket connection opening events $ws->on('Open', function ($ws, $request) { echo $request->fd . 'I'm connected'; }); //Listening for WebSocket message events $ws->on('Message', function ($ws, $frame) { //Convert the json string passed from the foreground into an array $params = json_decode($frame->data, true); //Judge whether it is a heartbeat message. If it is a heartbeat message if (isset($params['type']) && isset($params['type'])=='active'){ echo 'This is a heartbeat monitoring message'; }else{ //First judge whether the current user is connecting if (isset($params['uid']) && !empty($params['uid'] == 666)) { //Go to the user table to query the current user fd $fd = 2; } else { $fd = 1; } //Customer service id $ws->push($fd, json_encode($params, JSON_UNESCAPED_UNICODE)); } }); //Listen for WebSocket connection closing events $ws->on('Close', function ($ws, $fd) { echo "client-{$fd} is closed\n"; }); $ws->start();
5, The code has been written
1. Upload the server code to the Linux operating system
2. Then switch to this directory and run php wechat_websocket.php
