需求描述很简单: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 通信相关推荐

  1. android消息队列模型,Android 消息队列机制

    在非UI线程使用Handler进行线程通信时,一般都需要进行3个步骤: 创建Looper Looper.prepar() 创建Handler 启动消息循环Looper.loop() 通过这3步,基本就 ...

  2. 【go-zero】go-zero 与 amqp go整合 Rabbitmq 实现消息推送 go 消息队列 (best practice)

    目录 RabbitMq安装与go-zero框架整合使用 一.RabbitMq 1.打开 RabbitMq 进行简单地配置 2.Admin创建一个virtual Host 3.Exchanges创建交换 ...

  3. 消息队列之推还是拉,RocketMQ 和 Kafka是如何做的?

    今天我们就来谈一谈消息队列的推拉模式,这也是一个面试热点,例如你在简历里面写了 RocketMQ ,基本上会问你 RocketMQ 采用的是推模式还是拉模式啊?是拉模式?不是有 PushConsume ...

  4. 消息队列之推还是拉,RocketMQ 和 Kafka 是如何做的?

    每个时代,都不会亏待会学习的人 大家好,我是 yes. 今天我们就来谈一谈消息队列的推拉模式,这也是一个面试热点,例如你在简历里面写了 RocketMQ ,基本上会问你 RocketMQ 采用的是推模 ...

  5. rocketmq广播消息为什么不能重试_几分钟带你看懂“消息队列和RocketMQ”的入门总结

    消息队列扫盲 消息队列顾名思义就是存放消息的队列,队列我就不解释了,别告诉我你连队列都不知道似啥吧? 所以问题并不是消息队列是什么,而是 消息队列为什么会出现?消息队列能用来干什么?用它来干这些事会带 ...

  6. 阿里云消息队列 RocketMQ 5.0 全新升级:消息、事件、流融合处理平台

    从"消息"到"消息.事件.流"的大融合 消息队列作为当代应用的通信基础设施,微服务架构应用的核心依赖,通过异步解耦能力让用户更高效地构建分布式.高性能.弹性健壮 ...

  7. thinkphp5 消息队列thinkphp-queue扩展

    1.简介 thinkphp-queue是thinkphp的一个第三方扩展, 内置了 Redis,Database,Topthink ,Sync这四种驱动,推荐使用redis 2. 下载 和安装 com ...

  8. 云栖发布|阿里云消息队列 RocketMQ 5.0:消息、事件、流融合处理平台

    简介:RocketMQ5.0 的发布标志着阿里云消息正式从消息领域正式迈向了"消息.事件.流"场景大融合的新局面. 引言:从"消息"到"消息.事件.流 ...

  9. PHP高级编程之消息队列

    1. 什么是消息队列 消息队列(英语:Message queue)是一种进程间通信或同一进程的不同线程间的通信方式 2. 为什么使用消息队列 消息队列技术是分布式应用间交换信息的一种技术.消息队列可驻 ...

最新文章

  1. TLS/HTTPS 证书生成与验证
  2. 小样本点云深度学习库_2019-01-07-小样本深度学习
  3. maven构建SSM工程[应用]1
  4. c++ vector 保存指针
  5. Windows远程Linux/Ubuntu桌面
  6. 你真的了解Lambda表达式吗?
  7. 如何使用Hibernate将PostgreSQL枚举映射到JPA实体属性
  8. C语言代码规范(八)使用const修饰值不允许改变的变量
  9. .net 页面之间传值的几种方法!(转)
  10. 转 zookeeper启动为什么占用8080端口,修改哪个配置文件可以改变端口?
  11. OpenCV初探 —— 将OpenCV窗口链接在MFC的PictureControl控件中
  12. swagger 配置- ssm
  13. SEP14MP2卸载重装
  14. 华为 小米 OPPO 手机type-c快充接口 会用到什么胶水?
  15. 解决ios系统下微信页面无法播放背景音乐的问题
  16. 金融数量分析2:Markowitz均值方差模型
  17. autocad2014 第二次打开闪退_解决win10下autocad2014闪退的修复方法
  18. 【总结】反欺诈(Fraud Detection)中所用到的机器学习模型
  19. 深圳随手记(随手科技)面经(offer)
  20. 计算机语言与硬件相关,搞懂程序语言与计算机硬件的关系

热门文章

  1. 时下最流行前端构建工具Webpack 入门总结
  2. 使用ffmpeg视频切片并加密
  3. idea配置连接oracle数据库的pom文件中添加什么?
  4. 如何使用git上传本地文件到码云上【详细步骤】
  5. 网络安全公司奇安信集团是如何基于 Flink 构建 CEP 引擎实时检测网络攻击【未来不可忽视的网络安全】
  6. 大剑无锋之ArrayList中使用增强for循环能删除元素吗?【面试推荐】
  7. leetcode 334. Increasing Triplet Subsequence | 334. 递增的三元子序列(一种较trick的解法)
  8. leetcode 258. 各位相加(Java版)
  9. C#中重写(override)和覆盖(new)的区别
  10. MapReduce 论文翻译