如何在php后端及时推送消息给客户端

客户 0 97

如何在php后端及时推送消息给客户端,第1张

如何在php后端及时推送消息客户端
导读:后端代码pushphp

后端代码

pushphp

<php

use Workerman\Worker;

require_once '/Workerman/Autoloaderphp';

// 初始化一个worker容器,监听1234端口

$worker = new Worker('websocket://0000:1234');

// 这里进程数必须设置为1

$worker->count = 1;

// worker进程启动后建立一个内部通讯端口

$worker->onWorkerStart = function($worker)

{

// 开启一个内部端口,方便内部系统推送数据,Text协议格式 文本+换行符

$inner_text_worker = new Worker('Text://0000:5678');

$inner_text_worker->onMessage = function($connection, $buffer)

{

global $worker;

// $data数组格式,里面有uid,表示向那个uid的页面推送数据

$data = json_decode($buffer, true);

$uid = $data['uid'];

// 通过workerman,向uid的页面推送数据

$ret = sendMessageByUid($uid, $buffer);

// 返回推送结果

$connection->send($ret 'ok' : 'fail');

};

$inner_text_worker->listen();

};

// 新增加一个属性,用来保存uid到connection的映射

$worker->uidConnections = array();

// 当有客户端发来消息时执行的回调函数

$worker->onMessage = function($connection, $data)use($worker)

{

// 判断当前客户端是否已经验证,既是否设置了uid

if(!isset($connection->uid))

{

// 没验证的话把第一个包当做uid(这里为了方便演示,没做真正的验证)

$connection->uid = $data;

/ 保存uid到connection的映射,这样可以方便的通过uid查找connection,

实现针对特定uid推送数据

/

$worker->uidConnections[$connection->uid] = $connection;

return;

}

};

// 当有客户端连接断开时

$worker->onClose = function($connection)use($worker)

{

global $worker;

if(isset($connection->uid))

{

// 连接断开时删除映射

unset($worker->uidConnections[$connection->uid]);

}

};

// 向所有验证的用户推送数据

function broadcast($message)

{

global $worker;

foreach($worker->uidConnections as $connection)

{

$connection->send($message);

}

}

// 针对uid推送数据

function sendMessageByUid($uid, $message)

{

global $worker;

if(isset($worker->uidConnections[$uid]))

{

$connection = $worker->uidConnections[$uid];

$connection->send($message);

return true;

}

return false;

}

// 运行所有的worker(其实当前只定义了一个)

Worker::runAll();

启动后端服务

php pushphp start -d

前端接收推送的js代码

var ws = new WebSocket('ws://127001:1234');

wsonopen = function(){

var uid = 'uid1';

wssend(uid);

};

wsonmessage = function(e){

alert(edata);

};

后端推送消息的代码

// 建立socket连接到内部推送端口

$client = stream_socket_client('tcp://127001:5678', $errno, $errmsg, 1, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT);

// 推送的数据,包含uid字段,表示是给这个uid推送

$data = array('uid'=>'uid1', 'percent'=>'88%');

// 发送数据,注意5678端口是Text协议的端口,Text协议需要在数据末尾加上换行符

fwrite($client, json_encode($data)"\n");

// 读取推送结果

echo fread($client, 8192);

这里的uid不一定是用户的id,也可以理解为任务id即 taskid

以上代码亲测可以直接使用

1首先,了解socket的连接过程:

1)服务器监听;2)客户端请求;3)连接确认(具体详情可以见,我在这也就不多说了)。

2socket通信机制:

服务器端

  一、创建服务器套接字(CREATE)。

  二、服务器套接字进行信息绑定(BIND),并开始监听连接(LISTEN)。

  三、接受来自客户端的连接请求(ACCEPT),并创建接收进程。

  四、开始数据传输(SEND、RECEIVE)。

  五、关闭套接字(CLOSESOCKET)。

客户机端

  一、创建客户机套接字(CREATE)。

  二、与远程服务器进行连接(CONNECT),如被接受则创建接收进程。

  三、开始数据传输(SEND、RECEIVE)。

  四、关闭套接字(CLOSESOCKET)。

具体在Java中的实现是:

服务器端:

1)创建ServerSocket,需要使用端口号进行标识,以便客户端进行连接。

如:ServerSocket serverSocket = new ServerSocket(9999);

2)创建Socket获取连接

如: Socket socket = serverSocketaccept();

3)便可以进行通信内容传输了。

客户端:

1)创建Socket,进行与服务器连接,需要填写服务器ip,以及服务器的端口号

如:Socket socket = new Socket("127001", 9999);

2)进行通信内容的传输。

以上只是一个简单的socket通信案例,想要了解的可以进入该链接下载:http://downloadcsdnNET/detail/xia09222826/8244423

3利用socket通信进行服务器端到客户端的消息推送的思路:

客户端登录后发送一个消息给服务器端,用一个标识作为用户客户端程序关闭后服务器端是否推送消息给客户端,如果有则进行消息推送,如果没有则不进行消息推送,而当程序运行时就是一般的socket通信,也就是服务器端写一条消息推送给客户端,客户端便可以接收,并在消息栏上显示,点击消息栏进行相应的界面即可。

服务器就不多说了,方法是差不多的。

客户端:

需要使用Service来进行监听:

[java] view plain copy

print

public class PushService extends Service {

private PushClient mClient;

private Handler mHandler;

@Override

public IBinder onBind(Intent intent) {

return null;

}

@Override

public void onCreate() {

superonCreate();

initHandler();

}

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

mClient = new PushClient(new InetSocketAddress("1921684101", 9999),

mHandler);

mClientstart();

return superonStartCommand(intent, flags, startId);

}

@Override

public void onDestroy() {

if (mClient != null) {

mClientdisConnect();

}

superonDestroy();

}

/

初始化Handler

/

private void initHandler() {

mHandler = new Handler(new Callback() {

@Override

public boolean handleMessage(Message msg) {

switch (msgwhat) {

case ConstPUSH_MSG:

String pushMsg = msgobjtoString();

showNotification(pushMsg);

break;

default:

break;

}

return false;

}

});

}

/

在状态栏显示通知

/

@SuppressWarnings("deprecation")

private void showNotification(String msg) {

// 创建一个NotificationManager的引用

NotificationManager notificationManager = (NotificationManager) getSystemService(androidcontentContextNOTIFICATION_SERVICE);

// 定义Notification的各种属性

Notification notification = new Notification(Rdrawableic_launcher,

msg, SystemcurrentTimeMillis());

// FLAG_AUTO_CANCEL 该通知能被状态栏的清除按钮给清除掉

// FLAG_NO_CLEAR 该通知不能被状态栏的清除按钮给清除掉

// FLAG_ONGOING_EVENT 通知放置在正在运行

// FLAG_INSISTENT 是否一直进行,比如音乐一直播放,知道用户响应

notificationflags |= NotificationFLAG_AUTO_CANCEL; // 表明在点击了通知栏中的"清除通知"后,此通知不清除,经常与FLAG_ONGOING_EVENT一起使用

// DEFAULT_ALL 使用所有默认值,比如声音,震动,闪屏等等

// DEFAULT_LIGHTS 使用默认闪光提示

// DEFAULT_SOUND 使用默认提示声音

// DEFAULT_VIBRATE 使用默认手机震动,需加上<uses-permission

// android:name="androidpermissionVIBRATE" />权限

notificationdefaults = NotificationDEFAULT_SOUND;

// 设置通知的事件消息

CharSequence contentTitle = msg; // 通知栏标题

CharSequence contentText = msg; // 通知栏内容

Intent notificationIntent = new Intent(this, TestActivityclass); // 点击该通知后要跳转的Activity

PendingIntent contentItent = PendingIntentgetActivity(this, 0,

notificationIntent, 0);

notificationsetLatestEventInfo(this, contentTitle, contentText,

contentItent);

// 把Notification传递给NotificationManager

notificationManagernotify(0, notification);

}

这样就可以在将接收到的消息在消息栏上显示了,点击后便可以进入相应的界面了。

消息推送(Push)指运营人员通过自己的产品或第三方工具对用户移动设备进行的主动消息推送。用户可以在移动设备锁定屏幕和通知栏看到push消息通知,通知栏点击可唤起APP并去往相应页面。我们平时在锁屏上看到的微信消息等等都属于APP消息推送行列。 推送(Push)是一种技术概念,是指从服务端实时发送信息到客户端。应用想实现消息推送功能必须使用第三方或者自己研发,

第三方推送工具推荐使用极光推送,极光推送是经过考验的大规模 App 推送平台,每天推送消息量级为数百亿条。 开发者集成 SDK 后,可以通过调用 API 推送消息。同时,极光推送提供可视化的 web 端控制台发送通知,统计分析推送效果。 极光推送提供四种消息形式:通知,自定义消息,富媒体和本地通知,消息送达率高,可有效提供APP运营效率

一、消息推送基础

消息推送,就是在互联网上通过定期传送用户需要的信息来减少信息过载的一项新技术。推送技术通过自动传送信息给用户,来减少用于网络上搜索的时间。它根据用户的兴趣来搜索、过滤信息,并将其定期推给用户,帮助用户高效率地发掘有价值的信息

当我们开发需要和服务器交互的移动应用时,基本上都需要和服务器进行交互,包括上传数据到服务器,同时从服务器上获取数据。

一般情况下,客户端与服务器之间通讯客户端是主动的,但这就存在一个问题就是一旦服务器数据有更新或者服务器要下发通知给客户端只能等客户端连接的时候才能实现。这种方式使消息失去了实时性。

如何使客户端能够实时的收到服务器的消息和通知,总体来说有两种方式,第一种是客户端使用Pull(拉)的方式,就是隔一段时间就去服务器上获取一下信息,看是否有更新的信息出现。第二种就是 服务器使用Push(推送)的方式,当服务器端有新信息了,则把最新的信息Push到客户端上。这样,客户端就能自动的接收到消息。 

虽然Pull和Push两种方式都能实现获取服务器端更新信息的功能,但是明显来说Push方式比Pull方式更优越。因为Pull方式更费客户端的网络流量,更主要的是费电量,还需要我们的程序不停地去监测服务端的变化。  

二、几种常见的解决方案实现原理

1)轮询(Pull)方式:客户端定时向服务器发送询问消息,一旦服务器有变化则立即同步消息。

2)SMS(Push)方式:通过拦截SMS消息并且解析消息内容来了解服务器的命令,但这种方式一般用户在经济上很难承受。

3)持久连接(Push)方式:客户端和服务器之间建立长久连接,这样就可以实现消息的及时行和实时性。

三、消息推送解决方案概述

A、C2DM云端推送方案

在Android手机平台上,Google提供了C2DM(Cloudto Device Messaging)服务。Android Cloud to Device Messaging (C2DM)是一个用来帮助开发者从服务器向Android应用程序发送数据的服务。该服务提供了一个简单的、轻量级的机制,允许服务器可以通知移动应用程序直接与服务器进行通信,以便于从服务器获取应用程序更新和用户数据。

该方案存在的主要问题是C2DM需要依赖于Google官方提供的C2DM服务器,由于国内的网络环境,这个服务经常不可用。

B、MQTT协议实现Android推送

采用MQTT协议实现Android推送功能也是一种解决方案。MQTT是一个轻量级的消息发布/订阅协议,它是实现基于手机客户端的消息推送服务器的理想解决方案。

商家的后台管理系统实现新订单提醒推送功能,利用Spring Boot + WebSocket实时消息推送的方式进行实现。

引入依赖,我使用的是SpringBoot版本226RELEASE,自动管理依赖版本

配置类WebSocketConfig,扫描并注册带有@ServerEndpoint注解的所有websocket服务端

新建WebSocketServer类,WebSocket服务端是多例的,一次WebSocket连接对应一个实例

辅助类

新建一个测试类,用于向客户端发送推送消息

1、 启动服务器程序,提供WebSocket服务。

2 、打开前端html客户端页面,连接WebSocket服务器。

3、向客户端发送推送消息

4、客户端收到新订单推送消息

当我们在本地开采用WebSocket用IP连接时是OK的,例如

当我们上线后,用Nginx部署,并用域名连接时就会失败。此时只需要在Nginx配置文件里加入一些配置即可。配置如下

参考文章

Websocket实时推送消息

阿里云折扣快速入口

因为情绪严重透支。

当一个人对自己要做的事,感受不到任何价值和意义,还不被身边人所理解时,情绪就会失控,开始大量损耗。

生活中,你是不是有过这些崩溃瞬间:

明明内心充满焦虑,表面却要强装佛系。

即使晚上10点就睡,白天却依旧困得要死。

有时想睡睡不着,该起的时候又醒不了。

你也试过各种看起来很牛x的精力、时间管理法,尝试通过列清单,进行按部就班的生活来缓解自己的疲惫。

但,可能一两件鸡毛蒜皮的小事,就会打破你的计划和心态,让你从干劲满满一下子变得对什么都提不起劲,甚至患上严重的「拖延症」。

这并不是你意志力不坚定,或者计划做得不够完美导致的。

而是因为你的「情绪收支」严重失衡,支出远远超过了收入。

1)情绪大量支出

美国社会学家Hochschild,曾提出过一个理论:

我们日常除了体力和脑力劳动之外,还有一个被我们经常忽视了的劳动——情绪劳动。

他指出,不管任何工作,只要涉及人际互动,都可能需要进行情绪劳动

但事实上,在内卷化严重的当下,不仅仅是工作,只要你活着,活在这个社会中,情绪劳动就不会停止。

学校里,和同学、室友打交道。

工作上,完成自己并不喜欢的工作。

感情中,应付各种小摩擦,小矛盾。

生活中,下雨天挤公交地铁。

各种看似很小的事情,都在耗费着你的情绪。

情绪就像一笔资产,你越长大,面对的事情越多,支出就越多。

2)情绪收入微薄

如今的年轻人都特别丧。

很大一个原因就是,情绪投资出去后,得不到相应的回报。

充满抱负地进入社会,却发现自己拼死累活996,是在为老板创造价值,而不是自己。

于是,从工作中得到「价值感」越来越低。

努力打工,却发现永远追不上房价。

不知道努力的意义在哪里,随之「意义感」也逐渐模糊。

互联网的快速发展,公众号、某乎、某站让我们看到了更大的世界。

你会发现,不管怎么做,同龄人里总是有比你更出色的,上更好的学校,赚更多的钱,开更豪的车,泡更靓的妞。

最终,同样的付出,同样的成就,带给你的「成就感」却越来越低。

以前似乎还不错的成就,在这个时代下,变得不值得一提,导致明明挺优秀的一批人,却变得喜欢否定自己,给自己贴上了「一事无成」的标签。

你看,明明我们这批人,比以往任何时代都更努力,投入得更多,但得到的价值感、意义感、成就感却越来越微薄。

面对这种付出远大于收获的局面,大脑不乐意了,于是,你也就累了。

就像写这篇回答一样,如果不是有大家的点赞和肯定,我也难以坚持到现在。所以,这里铁木君非常感谢一下大家长久以来的点赞和支持~

说回疲惫。

虽然心累看起来并不致命,但并不代表没关系。

其一是因为,如果不改善,它会严重影响你日常效率,不管是工作,还是人际,都会被严重阻碍。

二来,长期心累,会让你逐渐丧失掉快乐的能力。

不知道你有多久没有感受到快乐了:

小时候,一颗糖、一个玩具或许就能让我们开心很久。

再后来,每天能偷摸玩上1、2个小时的电脑,就心满意足的不行。

而现在,你有吃不完的零食,手机想玩多久就玩多久,但你还记得上一次发自心内的快乐,是在什么时候吗?

其实,我们容易心累,并不是做的不够多,而是做的太多,甚至满出来了。

超载,然后导致了透支。

比起加加加,缓解这种情绪、心理上的疲劳,更有效的是减减减。减少情绪无意义地损耗,提高正面情绪的收益,以及对自我的认可,心累也就被解决掉了。

如果你准备好了,点个赞,让我们继续往下,消灭疲劳:

1、卸载那些大量耗费你时间、情绪的APP,减少无意义信息摄入

手机最好也是最危险的一点,就是让你知道的更多了。

各类媒体,app叮咚叮咚给你实时推送各类消息:

超级大瓜!一线顶流XX婚外恋被爆!

某聪又开撕,这次竟是舔狗人设?

90后的你还不知道这件事,就要被时代淘汰了!

通过一块小方块,你每天接收到的信息,数量、刺激程度都是爆炸性的。

但你停下来仔细想一想,有些事其实和你八竿子打不到一块,你不看也根本不会有任何损失。

相反,你看得越多,被煽动的情绪,蜂拥而出的焦虑会大量消耗掉你的内心能量,让你陷入疲惫。

比起手机的碎片信息,好的阅读习惯是这个时代更稀缺的能力,看一本书或许没多大效果,但十本二十本,长期下来不仅能丰富你的视野,打开思维格局,同时也能锻炼你的心性,稳扎稳打实现真正的高效成长。如果你不知道读什么,别担心,可以关注我的公众号铁木君,我把精心整理的3000本优质书单分享给你。

2、降低期待,100分很难,只要做到70分就行了

很多人之所以做什么都累,在于开始前,对自己要做的事情投入了过多期待,给了自己太大的压力。

在预期管理中,预期分成两部分:「预期快乐」和「预期诱惑」

就是当你想做一件事,过高的预期快乐,会让你只关注美好、顺利的一面,忽视可能遇到的问题,从而高估自己的能力,诱惑你定下一个难以实现的目标。

直到真正开始做,预期和实际的巨大落差,就会变成你的挫败感。

落差越大,挫败感就越强。

所以,从现在开始,如果你决心做一件事,先试着降低你的期待。

举个简单的小栗子,我最开始写作时,一心想着赚钱,热血澎湃地给自己定下来一个目标,每天坚持2k字,每个月投稿赚1000。

看似很热血,但事实上这种巨大的压力,对当时新手的我极不友好,没几天就让我对创作产生了恐惧,即使后来赚到了一些小钱,也因为与每月1000的目标有巨大差距,极大地打击了创作热情。

所以,后来我调整了策略。

把坚持每天2k字,调整为每天200字。

把每个月投稿赚1000,变为半年内赚到100。

看起来目标一下子拉胯了很多,但实际上,我比之前完成的更好,虽然写的字数变少,但更愿意写东西,也更容易坚持了。

而当我稿费超过100后,想的是「我可以做得更好」,而不是之前「我还不远远够好」的消极思想。

你看,有时候降低一下自己的期待,看似变得不完美了,但你可能会比以前做得更好。

3、适当放松,休息一会并不会让你被时代抛弃

这些年在各种媒体极端宣传下,导致各个年龄层、群体都陷入焦虑中:身份焦虑、中年危机、外貌焦虑、成长焦虑

以致于每个人都把自己逼得死死的,一点也不敢松懈。

在学校,往死里学;在公司,往死里加班;在健身房,往死里练。

看似付出了很多,但最终身心俱疲,反而走向下坡。

其实每个人都有自己的节奏,你要做的不是跟着别人的节奏拼命狂奔,而是慢慢摸索出自己的节奏,按着自己的方式,有条不紊地前进。

这样就足以已经完爆一群人。

这里分享给大家一个小技巧,看纪录片是个既能放松,同时又能开阔你眼界,提升认知的好方法。每当我累了的时候,就会找一部制作精良、画面宏伟的纪录片,让自己沉浸其中,放松身心。

如果你不知道怎么找优质纪录片,关注我的公众号铁木君,我早已准备好精心挑选的22部超高分且精选的神级纪录片,不仅包你享受到高清待遇,还大大节省你寻找好片的时间,让你在本就不多的空闲时间得到精神享受~

4、说干就干,减少心理建设时间

当你决定开始做一件事时,不要考虑太多「如果失败怎么办?」的问题。

没有开始,就等于是另一种失败。所以,动起来比什么都重要。

其次,很多倒在开始之前的人,并不是要做的事情有多难有多累,而是在做之前,胡思乱想太多。

越想越复杂,越想越困难,于是,还没开始,思想就疲了,身体也一起疲了。

这种自我斗争而耗费掉的大量情绪和精力,就是无意义的「内耗」。

所以,要做什么,有什么想法,直接开干。干1分钟也是干。

而且很多时候,当你没有那么重的思想包袱时,你会发现自己远比想象的能坚持更久,变专注的同时,源源不断产生成就感,也会让你保持长时间的旺盛精力。

打败你的不是挫折本身,而是你对挫折所抱持的态度!

如果你总是害怕失败,过度期待成功,给自己的精神套上枷锁负重前行,那这条路注定从一开始就充满了疲惫。

你不一定要功成名就,普普通通也是一种人生。

你不一定要年薪百万,家庭幸福美满也是成功。

这个时代,我们缺的不是向上生长的蛮力,而是在变得拧巴、伤痕累累后,学会重新认可自己。

当你开始放下对自我的严苛,你会发现轻松上不少,所有的事情也可能做得更好。

最后,看到这,就足以说明你意志力坚定,超过了90%的人,所以别多想,别再否定自己,改变自己,从为自己点个赞开始~

最后,欢迎关注我的公众号「铁木君」,我会把我的奋斗历程无条件与你分享。比如我如何毕业两年,就从一个普通实习生,到两家文化传媒公司创始人,如何寻找创业商机、有什么成长逆袭经验等。

我也会分享跟许多大牛学到的理财秘诀,3000本优质书籍和私人书单,高效有趣的英语学习法,以及无痛戒掉手机、养成自律的变好方法,还有一份编程+PS+PPT+Excel职场成长大礼包一起分享给你,让你更好提升自己。

我还在公众号里准备了近百篇优质文章,做好了分类,能让你在21天内从身体到思维改头换面,期待你的到来和蜕变。

我是号主铁木君,专注于大脑强化。

你也可以继续阅读我的内容,下面是我在知乎写得最好的几篇回答,强烈推荐你看看:

1、有哪些令人叫绝的心理学效应?

2、什么事情是你上了大学后才知道?

3、有哪些细微但是高效有用的习惯?

APP消息推送方法如下:

1、选择合适的时间进行推送,尽量避开用户休息时间(晚上22:00-早上8:00)推送,减少对用户的干扰。

2、一切从用户需求出发,精准推送。根据用户的地理位置、渠道、活跃度等维度对用户分群,从数据去提炼用户需求和使用场景,对不同的用户群推送不同的内容,能大幅度提高消息的准确度和匹配度。

3、结合热点,挖掘用户喜闻乐见的内容进行推送,用户关注度更高。以下是两个健身类App的消息推送对比,尽管都是下午时间段推送,但是第二个结合统计数据和好友PK的消息,更能激发起用户的锻炼欲望;

消息推送选择一家专业的平台,例如极光,极光发布了整合APP、微信公众号、微信小程序、5G消息、短信、邮件、支付宝生活号、钉钉 7大消息通道的统一消息系统-极光UMS,旨在通过该一体化消息下发平台,助力行业客户实现多通道高效精准触达目标用户。