微信小程序Session问题_finQiQi的博客-CSDN博客_小程序session

mikel阅读(479)

微信小程序——session
今天做微信小程序的时候,遇到一个问题,就是微信虽然提供了类似于ajax的数据通讯工具wx.request,但是因为不是浏览器,因此这个请求是不会带有sessionid的,那么今天就写一篇来记录如果解决微信小程序session的问题。

sessionid有什么用
因为我只写java web多,所以就以java web为主。那么写过java web的都知道,request是一次请求,session是一个会话周期,但是后台是如何识别请求是属于哪个session的呢?这就要降到cookie和session的关系。

我们都知道,session是服务器维护的会话,cookie是客户端(浏览器)持有的保存一些数据的,那么session实际上是通过cookie识别的。(因此当用户浏览器禁用cookie,也就代表服务器端session也被禁用了,无法得知访问是属于哪个session,因此就不存在session了。但是也不代表完全无法得到)那么当浏览器第一次访问网站网站会在response的header中添加一个叫做Set-Cookie的字段,这个字段的含义就是让浏览器将这里面的每条数据都放到你的cookie里面,这对于用户开发者都是不可见的,浏览器会自动放入cookie,而每次请求都会带着set-cookie里面的数据在cookie里,因此服务端只需要看一下cookie里面的sessionid就知道是来源了。在jsp中是jessionid这个值。

针对wx.request添加header
那么知道了原理,我们就可以手动模仿浏览器自动添加cookie这一步,那么app.js里面有一个onShow/onLaunch,在这步里面,我们可以使用一个wx.request去访问我们的后台,那么后台的服务器这时候是可以拿到第一个sessionid的,那么服务端将这个sessionid回复给我们,我们就可以记录下这个header。
首先在我们的app.js全局数据中添加header

globalData: {
userInfo: null,
header: {
‘Cookie’: ”
}
}

这里面可以放我们的cookie,然后请求服务端返回当前会话的sessionid
客户端代码:

wx.request({
url: app.globalData.requestUrl,
data: {
code: res.code
},
success: function (res) {
let ret = res.data;
if (ret.status == 200) {
// 添加到全局数据的header中
app.globalData.header.Cookie = ‘JSESSIONID=’ + ret.data.sessionid;
}
}
})

服务端代码:
ret.put(“sessionid”, request.getSession().getId());
很简单就能直接获得我们的id,这样子,我们就完成了header的获取

那么每次我们的wx.request,就要带上这个header
代码:

wx.request({
url: app.globalData.requestUrl,
// header中添加我们预先放入全局数据中的header,完成session的手动添加,那么就完成了会话的设置
header: app.globalData.header,
method: ‘GET’,
dataType: ‘json’,
success: function(res){
console.log(res.data.data.url)
that.setData({
captcha: res.data.data
})
}
})

图片显示问题
因为有些时候可能需要验证码,而验证码是放到session中的,那么如果直接选择访问服务器返回的验证码地址,可能取出来的就是null了。

比如我们的服务器返回一个url,而这个url实际上是取session中的验证码来生成图片,那么可能就存在问题。

因此,这就是当浏览器禁用了cookie的时候,我们可以通过URL获得sessionid

对于java web来说,url;jessionid=就可以达到和设置header一样的效果,就能解决非request的session问题了

总结
两种办法:
1、针对wx.request,采用全局数据保存sessionid的方式,手动每次请求添加进请求体中
2、针对图片资源,采用url传session方式,将sessionid放入url,可以起到一样的效果
————————————————
版权声明:本文为CSDN博主「finQiQi」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/a610616898/article/details/79413368

微信小程序开发--网络请求封装 - 掘金

mikel阅读(505)

来源: 微信小程序开发–网络请求封装 – 掘金

 1、背景

在做微信小程序开发的时候难免会涉及到网络请求操作,小程序提供的原生网络请求的api如下所示:

wx.request({
  url: 'https://test.com/******', //仅为示例,并非真实的接口地址
  data: {
    x: '',
    y: ''
  },
  header: {
    'content-type': 'application/json' // 默认值
  },
  success (res) {
    console.log(res.data)
  }
})
复制代码

其中 url: 为请求的后台接口地址;

data: 为请求接口需要携带的参数;

header:设置请求的 header,content-type 默认为 application/json,

success: 为请求成功后的回调,res包含请求成功后返回的数据。

更多关于 wx.request的用法可以查看官方介绍。

小程序wx.request官网api介绍

那既然官方已经提供有api,为什么还需要进行二次封装呢?

2、二次封装的原因

第一点、避免重复代码

避免重复代码主要体现在以下几点:

1) 我们公司调用后台接口,除了登录接口外,其它的接口请求都需要在请求头中加入token,如果不做封装的情况下,每次调用网络请求都需要传token,很麻烦。

2)在网络请求的时候往往需要给个加载框,提示用户正在加载…. 如下图所示:

如果不做封装,在每个网络请求的地方如果需要弹出加载框,都需要重复写这一段代码:

请求开始的时候,显示加载框。

请求结束的时候,隐藏加载框:

第二点、避免回调地狱

一个页面如果有多个网络请求,并且请求有一定的顺序,wx.request 是异步操作,那么最直接的结果就如下所示代码:

onLoad: function () {
    wx.request({
      url: 'https://test.com/api/test01',
      success:res=>{
        wx.request({
          url: 'https://test.com/api/test02',
          success: res=>{
            wx.request({
              url: 'https://test.com/api/test03',
              success: res=>{
                testDataList: res.content
              }
            })
          }
        })
      }
    })
  },
复制代码

是不是很像俄罗斯套娃。

为了避免这种写法,当然进行封装了,在这个地方用到了Promise。

关于Promise的介绍可以到廖雪峰的官方网站去查看,有详细的介绍。

Promise – 廖雪峰的官方网站研究互联网产品和技术,提供原创中文精品教程 https://www.liaoxuefeng.com/wiki/1022910821149312/1023024413276544

3、具体的封装实现

工程结构:

139F7EF1-50C8-4e90-BD17-4DA307C9302E.png

在utils文件夹下新建了两个文件。

1) httpUtils.js

网络请求的封装,具体代码如下:

const ui = require('./ui');
const BASE_URL = 'https://www.wanandroid.com'


/**
 * 网络请求request
 * obj.data 请求接口需要传递的数据
 * obj.showLoading 控制是否显示加载Loading 默认为false不显示
 * obj.contentType 默认为 application/json
 * obj.method 请求的方法  默认为GET
 * obj.url 请求的接口路径 
 * obj.message 加载数据提示语
 */
function request(obj) {
    return new Promise(function(resolve, reject) {
      if(obj.showLoading){
        ui.showLoading(obj.message? obj.message : '加载中...');
      }
      var data = {};
      if(obj.data) {
        data = obj.data;
      }
      var contentType = 'application/json';
      if(obj.contentType){
        contentType = obj.contentType;
      } 
  
      var method = 'GET';
      if(obj.method){
        method = obj.method;
      }
  
      wx.request({
        url: BASE_URL + obj.url,
        data: data,
        method: method,
        //添加请求头
        header: {
          'Content-Type': contentType ,
          'token': wx.getStorageSync('token') //获取保存的token
        },
        //请求成功
        success: function(res) {
          console.log('===============================================================================================')
          console.log('==    接口地址:' + obj.url);
          console.log('==    接口参数:' + JSON.stringify(data));
          console.log('==    请求类型:' + method);
          console.log("==    接口状态:" + res.statusCode);
          console.log("==    接口数据:" + JSON.stringify(res.data));
          console.log('===============================================================================================')
          if (res.statusCode == 200) {
            resolve(res);
          } else if (res.statusCode == 401) {//授权失效
            reject("登录已过期");
            jumpToLogin();//跳转到登录页
          } else {
            //请求失败
            reject("请求失败:" + res.statusCode)
          }
        },
        fail: function(err) {
          //服务器连接异常
          console.log('===============================================================================================')
          console.log('==    接口地址:' + url)
          console.log('==    接口参数:' + JSON.stringify(data))
          console.log('==    请求类型:' + method)
          console.log("==    服务器连接异常")
          console.log('===============================================================================================')
          reject("服务器连接异常,请检查网络再试");
        },
        complete: function() {
          ui.hideLoading();
        }
      })
    });
  }
  

  //跳转到登录页
  function jumpToLogin(){
    wx.reLaunch({
      url: '/pages/login/login',
    })
  }
  
  module.exports = {
    request,
  }
  
复制代码

代码中有详细的注释,在这里就不多做解释了。

2) ui.js

主要是对wx UI操作的一些简单封装,代码如下:

export const showToast = function(content,duration) {
    if(!duration) duration = 2000
    wx.showToast({
        title: content,
        icon: 'none',
        duration: duration,
    })
  }
  
  var isShowLoading = false
  export const showLoading = function(title) {
    if(isShowLoading) return
    wx.showLoading({
        title: title?title:'',
        mask:true,
        success:()=>{
            isShowLoading = true
        }
    })
  }
  
  export const hideLoading = function() {
    if(!isShowLoading) return
    isShowLoading = false
    wx.hideLoading()
  }
复制代码

3) 具体调用

在index.js 进行了网络请求,具体代码如下:

// index.js
const httpUtils = require('../../utils/httpUtils')
const ui = require('../../utils/ui')

Page({
  data: {
    str:null,
  },

  onLoad() {
  },

  //获取接口数据
  getNetInfo(){
    let obj = {
      method: "POST",
      showLoading: true,
      url:`/user/register?username=pppooo11&password=pppooo&repassword=pppooo`,
      message:"正在注册..."
    }
    httpUtils.request(obj).then(res=>{
      this.setData({
        str:JSON.stringify(res)
      })
      ui.showToast(res.data.errorMsg)
    }).catch(err=>{
      console.log('ERROR')
    });
  }
})
复制代码

好了,到这里也就结束了,如果上面的内容对你有所帮助不要忘记点个赞哟。

代码已经上传到了github上面,感兴趣的可以点击下载。

网络封装源码

作者:YMAndroid
链接:https://juejin.cn/post/7025471607367811080
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

layui iconfont.woff2?v=256 404报错 - 活着凑个人数 - 博客园

mikel阅读(342)

来源: layui iconfont.woff2?v=256 404报错 – 活着凑个人数 – 博客园

记录下日常使用中遇到的问题。

今天在发布的项目中,发现服务器上面运行的项目和我本地的运行不一样,前端框架使用的是layui,在使用layui  table的时候,工具的图标不显示,在本地是正常显示的,如下图是不显示的界面:

然后在控制台F12查看有一个报错,截图如下:

提示的是404,iconfont.woff2找不到,但是我服务器上面是有这个文件的,通过百度,找到问题所在,地址:layui iconfont.woff2?v=256 404报错

解决方法如下:

打开IIS,然后找到MIME类型,如下图所示:

然后双击打开,在右侧操作中选择添加,然后添加如下类型即可:

文件扩展名    MIME类型

.svg       image/svg+xml

.woff        application/x-font-woff

.woff2      application/x-font-woff

至此,问题解决!

另外注意一定要将Content/lib/layui/font/里的文件拷贝全,否则还是会显示不出图标

iconfont.ttf

iconfont.woff

iconfont.svg

iconfont.eot

ChatGPT如何注册使用(解决国外手机号验证码问题)_小懒懒懒懒的博客-CSDN博客

mikel阅读(727)

来源: ChatGPT如何注册使用(解决国外手机号验证码问题)_小懒懒懒懒的博客-CSDN博客

文章目录

一、OpenAI注册

二、国外手机号获取

三、GhatGPT初体验

一、OpenAI注册

科学/上/网/工/具

openai官网注册

二、国外手机号获取

但是注册最后需要国外手机号,我们可以从sms-active获取。

注册帐号,充值

大概0.2$(大概1.5rmb,不过最后我还剩4卢布,使用0.15 $就够了)

搜索openai,选择国家手机号(这里我选择的是印度,注意要去掉前面的(+91),直接输入后面的号码)

等待验证码

短信出现后输入即可注册成功,就可以尽情使用chatgpt啦。(我后来发现pc端直接进官网,不用登录和tz也可以用chatgpt(?)

手机和ipad则需要tz登录)

三、GhatGPT初体验

算法解释

算法举例

接下来准备学习一个项目,希望可以从chatgpt上获得一些帮助

————————————————

版权声明:本文为CSDN博主「小懒懒懒懒」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/yolo_______95/article/details/128456521

微信小程序将前端项目html转为wxml在线转化工具_VLilyV的博客-CSDN博客

mikel阅读(837)

来源: 微信小程序将前端项目html转为wxml在线转化工具_VLilyV的博客-CSDN博客

2020.10.22更新 哎服务器的事情真麻烦,有好多小伙伴在这里给我留言发消息:服务器又又又又挂了。我很少来 直到在公众号里看到一个人说 我才知道,赶紧又去买了一个服务器o(╥﹏╥)o(该网址永久有效,防止问题出现 你们可在公众号留言讨论:wander_yun 都是技术崽进去吧):http://www.wanderyun.com/blog/wxmlto.html

背景:去年小程序很火的时候,有个需求是把官网搬到小程序,然后后来直接放弃官网,有新产品页面的时候直接写到小程序里,但是我明白,终有一天,会把这些页面全部补充到官网中的,作为前端的我,要求自己不仅要快还要考虑长远,更要考虑少做重复性的工作,于是便有了写个一键转换工具的想法,你随便折腾,我给你提供工具可好?

为避免浪费大家的时间,先上图和链接看看是不是你要的。

 

地址:http://www.wanderyun.com/blog/wxmlto.html

哈哈,错了,不是上面那个,不过,也是关于小程序转化的,单位转化,很有用的哦,不过,如果有了下面那个工具,你或许就不需要上面的工具了,因为你可以在小程序里先全部用上px做单位,然后一键复制转化成rpx,挺好。

好的大神来了:

 

看到了么就是它!

工具地址:http://www.wanderyun.com/originality/wxmlto.html(服务器已挂)

2018.08.14更新:http://www.laoyouteam.com/originality/wxmlto.html(临时服务器)

2018.10.08更新:https://vlily.github.io//originality/wxmlto.html(github以后常用 也挂了 挂了o(╥﹏╥)o)

2020.10.22更新(永久有效):http://www.wanderyun.com/blog/wxmlto.html

使用之前希望你已经弄明白小程序与普通的前端项目区别在哪里。

这些个工具是我在网上找不到的,只看到一个插件,但是我个人不太喜欢插件这个东西,觉得很不方便而且很大

个人一直觉得创造力是个好东西,他就是源于生活,就是创造出不一样的。

有问题联系我撒。下方评论或者加我公众号:wander_yun

一起探讨。
————————————————
版权声明:本文为CSDN博主「VLilyV」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/VLilyV/article/details/79479862

html css 迁移微信小程序wxml wxss 修改建议 - 知乎

mikel阅读(449)

来源: html css 迁移微信小程序wxml wxss 修改建议 – 知乎

一般我们在微信公众号,或者其他web页面写好的html、css是可以直接迁移到微信小程序中的,但是迁移之后,需要对应的,修改一些标签和样式才行

这里面需要细心点,否则就会出现我那篇文章中出现的问题:

下面我们分别来说下html->wxml和css->wxss

html->wxml

通常来说,有以下几个标签需要注意:

<div></div> —–> <view></view>

<span></span> —–> <text></text>

<a href=””> —–> <view class=”a” data-href=””></view> 或 <view class=”a” bindtap=”goHref”></view> (goHref对应在js中写,可以是navigate或者redirect,根据实际情况自己选择)

<ul></ul> —–> <view class=”ul”></view>

<li></li> —–> <view class=”li”></view>

<img src=””> —–> <image src=””></image>

css->wxss

对应上面的wxml中的修改

div ———-> view

span ———-> text

ul ———-> .ul

li ———-> .li

a ———-> .a 或者wxml中如果不用 class=”a” ,那就用 > 或者 空格 来做子级分层也是可以的,但是建议直接加class,如果原css中是以 .demo > a 就会方便许多

img ———–> image

基本对应的,就是上面这些。

因为每个人的编码习惯可能不同,导致细节上后期修改需要根据自己的习惯调整,但原理不变。

样式调整好,最后一步就是修改原html中的变量了,比如你用的是smart等模板引擎,那就需要将里面的{$demo}换成你在小程序中js定义获取的新变量,比如{{demo}},还有for循环换成wx:for,if判断换成wx:if 等等,这里就不一一赘述了。

宝塔 workerman wss 反向代理 socket合法域名 小程序聊天 去掉端口_我是高手高手高高手的博客-CSDN博客_socket合法域名

mikel阅读(463)

来源: 宝塔 workerman wss 反向代理 socket合法域名 小程序聊天 去掉端口_我是高手高手高高手的博客-CSDN博客_socket合法域名

提前workerman已经配置好

一、带端口的配置(不在这里说配置,有其它说明教程)
小程序中聊天,需要设置socket合法域名:wss://www.xxx.com:2000

 

 

二、不带端口的设置
宝塔配置域名,处理wss通信服务
1、去域名服务商添加域名 wss.xxx.com
2、服务器申请SSL证书,并下载
3、宝塔添加域名,选纯静态即可

4、宝塔对应域名的设置,配置SSL证书,把刚刚下载的证书包打开,填充对应的内容,保存

5、宝塔对应域名的设置->配置文件,在server{ }内结尾处添加下面的内容

 

# 反向代理 转移到本地的websocket地址,wss://127.0.0.1:2000 ,对应 wss://card.xxxx.com:2000
location / {
proxy_redirect off;
proxy_pass https://127.0.0.1:2000;
proxy_set_header Host $host;
proxy_set_header X-Real_IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr:$remote_port;
proxy_http_version 1.1;
# 添加wss协议头专用的字段
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection “upgrade”;
}
主要是这两行:

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection “upgrade”;

 

参考:

workerman配置

https://blog.csdn.net/haibo0668/article/details/106681142

https://blog.csdn.net/haibo0668/article/details/108245320

https://blog.csdn.net/haibo0668/article/details/107186152
————————————————
版权声明:本文为CSDN博主「我是高手高手高高手」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/haibo0668/article/details/111356861

如何在小程序中实现 WebSocket 通信 - 腾讯云开发者社区-腾讯云

mikel阅读(405)

来源: 如何在小程序中实现 WebSocket 通信 – 腾讯云开发者社区-腾讯云

在以前的文章中,我们介绍了HTTP通讯,这种通讯有一个缺点,如果我想从直接从服务器发消息给客户端,需要客户端先发起HTTP请求后服务器才能返回数据,且后续服务器想发送数据给客户端都需要客户端先发起请求,但这种方案在一些特殊场景应用的时候非常消耗资源,比如聊天室,如果使用HTTP请求,需要客户端每隔一段时间就请求一次服务器,再由服务器返回数据。这种传统的模式带来很明显的缺点,即客户端需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。

在这种情况下,HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。WebSocket只需要与服务器进行一次握手,即可实现实时的数据连接,并且传输协议是全双工的,服务器可以随时主动向客户端发送数据,并且WebSocket协议在连接创建后,服务器和客户端之间交换数据时,用于协议控制的数据包头部相对较小,能明显降低服务器及客户端开销。

我们的小程序也支持WebSocket通信,如果你想为你的小程序实现聊天室、服务器推送、小程序之间数据交互等功能,那就非常有必要搭建一个WebSocket服务器来进行WebSocket通讯。这篇文章中,我们将简单介绍小程序WebSocket通信使用方法,并通过实例搭建一个WebSocket服务器。实现小程序与服务器之间的通讯。

在教程开始之前,需要搭建搭建好小程序的基础开发环境,关于如何配置,大家可以参考如何入门小程序开发这篇文章的入门教程。

服务器搭建

既然要实现WebSocket通讯,那必须要拥有一台WebSocket服务器,服务端的环境有很多选择NodeJS、PHP、Python等大部分主流语言都可以部署WebSocket服务,今天我们将教大家使用PHP语言进行环境部署,其他语言请同学们自行部署。

运行环境搭建

我这里以Ubuntu Server 16.04 LTS为例,我们需要安装php运行环境及NginxWeb服务,同时也需要申请免费的SSL证书域名,关于证书和域名的申请注册请参考如何快速搭建微信小程序这篇文章。注册完域名及证书申请,我们就可以开始部署服务器了!首先,登录服务器,执行下面的命令。

sudo apt update
sudo apt install php php-fpm php-curl nginx composer -y

安装完成后,使用浏览器访问你的服务器IP地址,如果看到下面的内容,则证明Web服务已经启动。

img

因为小程序获取远程数据,必须为HTTPS或WSS环境,所以目前搭建的环境,在小程序无法使用,接下来,我们将使用SSL证书加密小程序访问你服务器之间的流量。这里就需要刚才注册的域名及证书了。首先,将下载的证书,上传到你的服务器,并记录下这个位置。然后,我们将配置Nginx服务,以让其支持WSS流量。

我们找到/etc/nginx/conf.d文件夹,新建配置文件,为了方便后续修改,我将这里的配置文件修改为weixin.techeek.cn.conf大家可以根据自己的需求修改。

cd /etc/nginx/conf.d
sudo nano weixin.techeek.cn.conf

nano编辑器中,我们写下下面的代码

server {
        listen 443 ssl;
        server_name weixin.techeek.cn;
				index  index.php index.html index.htm;
				root /usr/share/nginx/html;
        ssl_certificate      /home/ubuntu/1_weixin.techeek.cn_bundle.crt;
        ssl_certificate_key  /home/ubuntu/2_weixin.techeek.cn.key;
        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;
        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location ~ .php$ {
        fastcgi_pass  unix:/run/php/php7.0-fpm.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
        location /
        {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header X-Real-IP $remote_addr;
        }
}

server {
        listen 80 default_server;
        server_name weixin.techeek.cn;
        root /usr/share/nginx/html;
        index index.php index.html index.htm;
        location / {
                try_files $uri $uri/ =404;
        }
}

一定注意,将文中server_name中的weixin.techeek.cn更换成你的域名。将ssl_certificatessl_certificate_key中证书的路径更换成你刚上传证书的路径。然后,执行下面的命令重启nginx服务。

sudo service nginx restart

之后,打开你电脑的浏览器,然后通过域名访问,注意,这里一定要在域名前加https://,比如我访问的域名https://weixin.techeek.cn/

1542188355313

如果域名前有小锁标志,则证明你已经配置成功,可以开始下一步了,这里502报错不用在意,因为我们还没有搭建WebSocket服务,所以服务器会返回502错误。

配置通讯域名

基本环境配置好之后,可以登录 微信公众平台 配置通信域名了。我们点击微信公众号右侧的设置,然后找到服务器域名配置。

1542188610710

进入微信公众平台管理后台设置服务器配置,如上图所示,需要将你的服务器域名配置为你自己的域名。我这里的域名是weixin.techeek.cn

WebSocket服务搭建

上述步骤准备完成后 ,就可以撰写WebSocket服务端的代码了,我这里使用的是PHP socket即时通讯框架Workerman来进行搭建。有了这个框架,我们就可以非常方便的搭建WebSocket服务。因为本文主要讲解小程序端的WebSocket的使用,关于Workerman的详细使用教程,可以参考Workerman官方手册,本文仅做基础环境安装的介绍。

首先,我们创建一个运行WebSocket服务的目录,我这里创建名为php-websocket-server,目录位置可以自定义,我这里就将项目放在ubuntu用户的根目录下。

mkdir /home/ubuntu/php-websocket-server
cd /home/ubuntu/php-websocket-server

接下来,我们使用composer包管理器安装WebSocket运行环境。因为某些原因,国内访问composer可能会报错,所以我们需要使用国内的composer镜像。然后就可以安装Workerman了。

sudo composer config -g repo.packagist composer https://packagist.phpcomposer.com
sudo composer update
sudo composer require workerman/workerman

安装完成后,默认情况下会有三个文件,composer.jsoncomposer.lockvendor这三个文件,如果没有,请重新执行上面的命令。

├── composer.json
├── composer.lock
└── vendor

安装完workerman依赖文件,我们就可以撰写系统所需的代码了。使用nano编辑器,新建一个可执行的php文件,我这里创建的文件名为webSocket.php,大家可自行更改。

nano webSocket.php

代码如下

<?php
require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Worker;
$ws_worker = new Worker("websocket://0.0.0.0:8080");
$ws_worker->count = 4;
$ws_worker->onMessage = function($connection, $data)
{
    $connection->send('hello ' . $data);
};
Worker::runAll();

这时,一个最基本的websocket服务就编辑完成了,这里的代码意思是,通过/vendor/autoload.php引入Workerman的php文件,然后在8080端口创建websocket服务,并设置进程为4个进程。然后执行onMessage回调函数,该函数接收客户端所发过来的数据$data,然后使用send方法将数据发回给客户端。

接下来,我们就可以运行服务器了,执行下面的代码即可运行。

sudo php webSocket.php start

如果看到类似下面的输出,证明我们websocket服务器已经启动,接下来就可以开始配置小程序端的代码了。

1542247109151

小程序端

连接服务器

小程序连接Websocket服务器是通过wx.connectSocket()API进行连接的,为了方便连接API,我们先看看官方的文档

属性

类型

是否必填

说明

url

string

开发者服务器 wss 接口地址

header

Object

HTTP Header,Header 中不能设置 Referer

protocols

Array.<string>

子协议数组

success

function

接口调用成功的回调函数

fail

function

接口调用失败的回调函数

complete

function

接口调用结束的回调函数(调用成功、失败都会执行)

我们看到只有url是必填项,其他属性可以不填,那么连接服务器就比较简单了,我们打开index.js文件,写下下面的代码。

Page({
onReady: function () {
	wx.connectSocket({
    url: 'wss://weixin.techeek.cn'
	})
},
})

有小程序开发经验的小伙伴都知道,这里的onReady是小程序的生命周期函数,负责在小程序初次渲染完成后执行的函数,这样我们编译完小程序,小程序就自动连接服务器。现在编译一下试试,咦,好像不行啊,怎么没看到小程序有反应。我们打开控制台,点击Network按钮,如果看到类似下面的内容,就证明你的小程序已经成功链接服务器了。

1542249696427

这里的HTTP状态码是101,101状态码是websocket特有的状态码,我们已经成功连接搭建的服务器。但是我们能不能直观点看到已经连接服务器呢?当然可以,参考文档使用success属性,我们在其中加入回调函数。修改代码如下。

Page({
  onReady: function () {
    wx.connectSocket({
      url: 'wss://weixin.techeek.cn',
        success: function (res) {
          console.log("连接服务器成功")
      },
      fail: function (res) {
        console.log("连接服务器失败")
      }
    })
  },
})

我们增加一个回调函数,如果服务器连接成功,向小程序控制台打印出连接服务器成功。反正打印连接服务器失败

1542250247835

当然,我们也可以将成功的内容展示给小程序前端,代码如下,首先修改index.wxml代码。

<view><text>连接服务器状态:{{status}}</text></view>

然后打开index.js文件,修改代码

Page({
  onReady: function () {
    var myThis = this;
    wx.connectSocket({
      url: 'wss://weixin.techeek.cn',
      success: function (res) {
        myThis.setData({
          status: "连接服务器成功"
        })
      },
      fail: function (res) {
        myThis.setData({
          status: "连接服务器失败"
        })
      }
    })
  },
})

现在重新编译小程序,你会看到类似这样的界面。

1542250497626

向服务器发送数据

服务器搭建我们说到,我们的服务器的代码内容是将小程序发给服务器的任意字符前加hello之后返回给小程序,现在,我们已经成功连接服务器了。接下来,我们需要修改代码,以便小程序将数据发给服务器。

官方文档中,使用wx.sendSocketMessage()API将数据发给服务器,根据官方文档,通过 WebSocket 连接发送数据。需要先wx.connectSocket连接服务器,并在 wx.onSocketOpen 回调之后才能发送。所以在调用wx.sendSocketMessage()前,需要先调用wx.onSocketOpen监听WebSocket连接是否打开。代码如下。

Page({
  onReady: function () {
    var myThis = this;
    wx.connectSocket({
      url: 'wss://weixin.techeek.cn'
    })
    wx.onSocketOpen(function (res) {
      myThis.setData({
        status: "websocket连接服务器成功"
      })
    })
  },
})

现在,我们就可以使用wx.sendSocketMessage()发送数据到服务器了,先看看官方文档,怎么使用。

属性

类型

是否必填

说明

data

string/ArrayBuffer

需要发送的内容

success

function

接口调用成功的回调函数

fail

function

接口调用失败的回调函数

complete

function

接口调用结束的回调函数(调用成功、失败都会执行)

我们只需要传data内容给API,就能发内容给服务器了,那么修代码内容如下。

Page({
    onReady: function () {
    var myThis = this;
    wx.connectSocket({
      url: 'wss://weixin.techeek.cn'
    })
    wx.onSocketOpen(function (res) {
      wx.sendSocketMessage({
        data: "你好",
        success: function (res) {
          console.log("数据已发给服务器")
        }
      })
      myThis.setData({
        status: "websocket连接服务器成功"
      })
    })
  },
})

现在,我们的数据已经可以发给服务器了,可是我们还没有看到服务器返回的数据,这时,我们就该使用另一个API了,监听WebSocket 接受到服务器的消息事件wx.onSocketMessage(),该API返回服务器发出的消息。但是onReady函数是页面加载就运行的,这时服务器还没反应过来,数据返回了没收到该怎么处理?我们可以引入另一个生命周期函数onLoad,这个函数是小程序负责监听页面加载的函数,我们可以将服务器消息事件监听的API写在这里,当接收到数据,由这个函数返回相关内容。所以代码如下。

Page({
  onReady: function () {
    var myThis = this;
    wx.connectSocket({
      url: 'wss://weixin.techeek.cn'
    })
    wx.onSocketOpen(function (res) {
      wx.sendSocketMessage({
        data: "你好",
        success: function (res) {
          console.log("数据已发给服务器")
        }
      })
      myThis.setData({
        status: "websocket连接服务器成功"
      })
    })
  },
  onLoad: function (options) {
    var myThis = this;
    wx.onSocketMessage(function (res) {
      myThis.setData({
        message: res.data
      })
    })
  },
})

为了方便观察服务器返回的数据,我们修改下前端,增加服务器消息监听的内容。

<view><text>连接服务器状态:{{status}}</text></view>
<view><text>服务器消息:{{message}}</text></view>

现在,重新编译,就能看到服务器返回Hello 你好的内容,我们发出的内容为你好,服务器在内容前加一个Hello然后返回给小程序。我们可以修改你好为任意内容,看看服务器能否正常返回相关内容。稍微优化下前端和后端代码,如下。

index.wxml

<button type="primary" bindtap="connect">连接webSocket服务器</button>
<button type="warn" bindtap="close">断开webSocket服务器</button>
<input placeholder="在这里输入你要发送的弹幕内容" bindblur="input"/>
<button bindtap="send">向webSocket服务器发送消息</button>
<view><text>连接服务器状态:{{status}}</text></view>
<view><text>服务器消息:{{message}}</text></view>

index.js

Page({
  connect() {
    var myThis = this;
    wx.connectSocket({
      url: 'wss://weixin.techeek.cn'
    })
    wx.onSocketOpen(function (res) {
      myThis.setData({
        status:"websocket连接服务器成功"
      })
    })
  },
  close(){
    var myThis = this;
    wx.closeSocket()
    wx.onSocketClose(function (res) {
      myThis.setData({
        status: "websocket服务器已经断开"
      })
    })
  },
send(){
  var myThis = this;
  wx.sendSocketMessage({
    data: this.inputValue,
    success: function (res) {
      console.log("发送信息")
      wx.showToast({
        title: '已发送',
        icon: 'success',
        duration: 1000
      })
    },
    fail: function (res) {
      myThis.setData({
        status: "请连接服务器"
      })
    }
  })
},
  input: function (e) {
    this.inputValue = e.detail.value
  },
  onLoad: function (options) {
    var myThis = this;
    wx.onSocketMessage(function (res) {
      myThis.setData({
        message:res.data
      })
      wx.showToast({
        title: '你收到来自服务器的消息',
        icon: 'none',
        duration: 2000
      })
    })
  },
})

1542253679047

这样,我们就实现了向服务器发送数据,同时服务器返回数据的全部流程。

服务器主动发送数据到小程序

有人可能会问,这个HTTP通信方式没有区别啊,还是小程序先请求数据到服务器,然后服务器返回数据啊,我没看到什么不同。虽然表现是这样,但是现在小程序和服务器是长连接状态,服务器可以直接推送内容到小程序,不信?我们试试。打开你的服务器Websocket.php文件,将代码修改为下面的内容。

<?php
require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Worker;
use Workerman\Lib\Timer;

$worker = new Worker('websocket://0.0.0.0:8080');
$worker->onWorkerStart = function($worker){
    Timer::add(10, function()use($worker){
        foreach($worker->connections as $connection) {
            $connection->send('你好!');
        }
    });
};

$worker->onMessage = function($connection, $data)
{
    echo $data . "\n";
    $connection->send('服务器已经收到了你的消息');
};
Worker::runAll();

然后运行服务器。

sudo php webSocket.php start

这行代码中,我们实现了小程序连接服务器后,服务器每隔10秒主动推送数据你好给小程序,无需小程序主动请求内容,同时,小程序发出的内容,可以在服务端显示。现在点击你小程序连接webSocket服务器按钮,看看效果。

1542254161118

然后我们向服务器发点消息试试。服务器也已经收到了小程序发出的数据。

1542254236499

总结

websocket通信在小程序端还是比较简单的,赶快去自己试试吧~后续我还会介绍一篇利用websocket通讯进行聊天室搭建的教程,喜欢的小伙伴请持续关注本专栏。腾讯云联合小程序给大家带来了小程序·云开发解决方案,为开发者提供完整的云端支持,弱化后端和运维操作,使用平台原生 API 进行核心业务开发,实现快速上线和迭代。欢迎免费使用!

原创声明,本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。