安卓+php推,使用 PHP 消息队列实现 Android 与 Web 通信
需求描述很简单:Android 发送数据到 Web 网页上。
系统: Ubuntu 14.04 + apache2 + php5 + Android 4.4
思路是 socket + 消息队列 + 服务器发送事件,下面的讲解步骤为 Android 端,服务器端,前端。重点是在于 PHP 进程间通信。
Android 端比较直接,就是一个 socket 程序。需要注意的是,如果直接在活动主线程里面创建 socket 会报一个 android.os.NetworkOnMainThreadException, 因此最好的方法是开个子线程来创建 socket,代码如下
private Socket socket = null;
private boolean connected = false;
private PrintWriter out;
private BufferedReader br;
private void buildSocket(){
if(socket != null)
return;
try {
socket = new Socket("223.3.68.101",54311); //IP地址与端口号
out = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(
socket.getOutputStream())), true);
br = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
connected = true;
}
然后是发送消息
public void sendMsg(String data){
if(!connected || socket == null) return;
synchronized (socket) {
try {
out.println(data);
} catch (Exception e) {
e.printStackTrace();
}
}
}
完成后还需要关闭 socket
private void closeSocket(){
if( socket == null) return;
try {
socket.close();
out.close();
br.close();
} catch (IOException e) {
e.printStackTrace();
}
socket = null;
connected = false;
}
注意这些方法都不要在主线程执行。
下面是服务器 PHP 端。
首先要运行一个进程来接收信息。
function buildSocket($msg_queue){
$address = "223.3.68.101";
$port = 54321;
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false){
echo "socket_create() failed:" . socket_strerror(socket_last_error()) . "/n";
die;
}
echo "socket create\n";
if (socket_set_block($sock) == false){
echo "socket_set_block() faild:" . socket_strerror(socket_last_error()) . "\n";
die;
}
if (socket_bind($sock, $address, $port) == false){
echo "socket_bind() failed:" . socket_strerror(socket_last_error()) . "\n";
die;
}
if (socket_listen($sock, 4) == false){
echo "socket_listen() failed:" . socket_strerror(socket_last_error()) . "\n";
die;
}
echo "listening\n";
if (($msgsock = socket_accept($sock)) === false) {
echo "socket_accept() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
die;
}
$buf = socket_read($msgsock, 8192);
while(true){
if(strlen($buf) > 1)
handleData($buf,$msg_queue); //见后文
$buf = socket_read($msgsock, 8192);
//看情况 break 掉
}
socket_close($msgsock);
}
也比较简单。这个进程是独立运行的,那么打开网页请求数据,需要从另一段脚本接入,下面就需要用到进程间通信,我选择消息队列,也就是上面的 $msg_queue 变量。
脚本主程序这么写。
$msg_queue_key = ftok(__FILE__,'socket'); //__FILE__ 指当前文件名字
$msg_queue = msg_get_queue($msg_queue_key); //获取已有的或者新建一个消息队列
buildSocket($msg_queue);
socket_close($sock);
其中的 ftok() 函数就是生成一个队列的 key,以区分。
那么handleData() 的任务就是把收到的消息放到队列里面去
function handleData($dataStr, $msg_queue){
msg_send($msg_queue,1,$dataStr);
}
Socket 进程脚本骨架
这样一来,其他进程就可以通过 key 找到这个队列,从里面读取消息了。使用这样可读
function redFromQueue($message_queue){
msg_receive($message_queue, 0, $message_type, 1024, $message, true, MSG_IPC_NOWAIT);
echo $message."\n\n";
}
$msg_queue_key = ftok("socket.php", 'socket'); //第一个变量为上方socket进程的文件名。
$msg_queue = msg_get_queue($msg_queue_key, 0666);
while(true){
$msg_queue_status = msg_stat_queue($msg_queue); //获取消息队列的状态
if($msg_queue_status["msg_qnum"] == 0) //如果此时消息队列为空,那么跳过,否则会读取空行。
continue;
redFromQueue($msg_queue);
}
现在就差最后一步,如何主动把数据发往前端?这要用到 HTML5 的新特性:服务器发送事件(要使用较新的非 IE 浏览器,具体查看这里)。直接看JS代码
var source = new EventSource("php/getData.php"); //Web 服务器路径
source.onmessage = function(event){ //消息事件回调
var resData = event.data;
document.getElementById("res").innerHTML=resData;
};
那么这个 getData.php 就是上面那个从消息队列获取数据的脚本。只是为了让它被识别为服务器事件,需要加一点格式上的说明,具体如下。
下面就可以开始运行,首先运行服务器
php socket.php
打印了 listening 就可以使用 Android 设备连接了。
然后再用 Web 上 JS 请求 getData 脚本,请求后前台可以不断地获得新的数据。需要注意的是消息队列可能会阻塞(消息量达到上限),再有就是 JS 本身消息机制的限制,因此丢失,延迟等现象频发。
Web 通信的老问题就是稳定性。以前老是怨恨 Web QQ 掉包,其实整个 Web 革命尚未成功。
希望与广大网友互动??
点此进行留言吧!
安卓+php推,使用 PHP 消息队列实现 Android 与 Web 通信相关推荐
- android消息队列模型,Android 消息队列机制
在非UI线程使用Handler进行线程通信时,一般都需要进行3个步骤: 创建Looper Looper.prepar() 创建Handler 启动消息循环Looper.loop() 通过这3步,基本就 ...
- 【go-zero】go-zero 与 amqp go整合 Rabbitmq 实现消息推送 go 消息队列 (best practice)
目录 RabbitMq安装与go-zero框架整合使用 一.RabbitMq 1.打开 RabbitMq 进行简单地配置 2.Admin创建一个virtual Host 3.Exchanges创建交换 ...
- 消息队列之推还是拉,RocketMQ 和 Kafka是如何做的?
今天我们就来谈一谈消息队列的推拉模式,这也是一个面试热点,例如你在简历里面写了 RocketMQ ,基本上会问你 RocketMQ 采用的是推模式还是拉模式啊?是拉模式?不是有 PushConsume ...
- 消息队列之推还是拉,RocketMQ 和 Kafka 是如何做的?
每个时代,都不会亏待会学习的人 大家好,我是 yes. 今天我们就来谈一谈消息队列的推拉模式,这也是一个面试热点,例如你在简历里面写了 RocketMQ ,基本上会问你 RocketMQ 采用的是推模 ...
- rocketmq广播消息为什么不能重试_几分钟带你看懂“消息队列和RocketMQ”的入门总结
消息队列扫盲 消息队列顾名思义就是存放消息的队列,队列我就不解释了,别告诉我你连队列都不知道似啥吧? 所以问题并不是消息队列是什么,而是 消息队列为什么会出现?消息队列能用来干什么?用它来干这些事会带 ...
- 阿里云消息队列 RocketMQ 5.0 全新升级:消息、事件、流融合处理平台
从"消息"到"消息.事件.流"的大融合 消息队列作为当代应用的通信基础设施,微服务架构应用的核心依赖,通过异步解耦能力让用户更高效地构建分布式.高性能.弹性健壮 ...
- thinkphp5 消息队列thinkphp-queue扩展
1.简介 thinkphp-queue是thinkphp的一个第三方扩展, 内置了 Redis,Database,Topthink ,Sync这四种驱动,推荐使用redis 2. 下载 和安装 com ...
- 云栖发布|阿里云消息队列 RocketMQ 5.0:消息、事件、流融合处理平台
简介:RocketMQ5.0 的发布标志着阿里云消息正式从消息领域正式迈向了"消息.事件.流"场景大融合的新局面. 引言:从"消息"到"消息.事件.流 ...
- PHP高级编程之消息队列
1. 什么是消息队列 消息队列(英语:Message queue)是一种进程间通信或同一进程的不同线程间的通信方式 2. 为什么使用消息队列 消息队列技术是分布式应用间交换信息的一种技术.消息队列可驻 ...
最新文章
- TLS/HTTPS 证书生成与验证
- 小样本点云深度学习库_2019-01-07-小样本深度学习
- maven构建SSM工程[应用]1
- c++ vector 保存指针
- Windows远程Linux/Ubuntu桌面
- 你真的了解Lambda表达式吗?
- 如何使用Hibernate将PostgreSQL枚举映射到JPA实体属性
- C语言代码规范(八)使用const修饰值不允许改变的变量
- .net 页面之间传值的几种方法!(转)
- 转 zookeeper启动为什么占用8080端口,修改哪个配置文件可以改变端口?
- OpenCV初探 —— 将OpenCV窗口链接在MFC的PictureControl控件中
- swagger 配置- ssm
- SEP14MP2卸载重装
- 华为 小米 OPPO 手机type-c快充接口 会用到什么胶水?
- 解决ios系统下微信页面无法播放背景音乐的问题
- 金融数量分析2:Markowitz均值方差模型
- autocad2014 第二次打开闪退_解决win10下autocad2014闪退的修复方法
- 【总结】反欺诈(Fraud Detection)中所用到的机器学习模型
- 深圳随手记(随手科技)面经(offer)
- 计算机语言与硬件相关,搞懂程序语言与计算机硬件的关系
热门文章
- 时下最流行前端构建工具Webpack 入门总结
- 使用ffmpeg视频切片并加密
- idea配置连接oracle数据库的pom文件中添加什么?
- 如何使用git上传本地文件到码云上【详细步骤】
- 网络安全公司奇安信集团是如何基于 Flink 构建 CEP 引擎实时检测网络攻击【未来不可忽视的网络安全】
- 大剑无锋之ArrayList中使用增强for循环能删除元素吗?【面试推荐】
- leetcode 334. Increasing Triplet Subsequence | 334. 递增的三元子序列(一种较trick的解法)
- leetcode 258. 各位相加(Java版)
- C#中重写(override)和覆盖(new)的区别
- MapReduce 论文翻译