WebSocket实现android消息推送

WebSocket是HTML5出的协议,基于TCP。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。

WebSocket协议之前,双工通信是通过多个http链接来实现,这导致了效率低下。WebSocket解决了这个问题。

有了websocket协议,服务器就可以主动给客户端发送消息,而不是要等客户端的轮询。

实现一个简单的Websocket服务器


#-*- coding:utf8 -*-import threading
import hashlib
import socket
import base64global clients
clients = {}#通知客户端
def notify(message):for connection in clients.values():connection.send('%c%c%s' % (0x81, len(message), message))#客户端处理线程
class websocket_thread(threading.Thread):def __init__(self, connection, username):super(websocket_thread, self).__init__()self.connection = connectionself.username = usernamedef run(self):print 'new websocket client joined!'data = self.connection.recv(1024)headers = self.parse_headers(data)token = self.generate_token(headers['Sec-WebSocket-Key'])self.connection.send('\
HTTP/1.1 101 WebSocket Protocol Hybi-10\r\n\
Upgrade: WebSocket\r\n\
Connection: Upgrade\r\n\
Sec-WebSocket-Accept: %s\r\n\r\n' % token)while True:try:data = self.connection.recv(1024)except socket.error, e:print "unexpected error: ", eclients.pop(self.username)breakdata = self.parse_data(data)if len(data) == 0:continuemessage = "来自服务端的消息: " + datanotify(message)def parse_data(self, msg):v = ord(msg[1]) & 0x7fif v == 0x7e:p = 4elif v == 0x7f:p = 10else:p = 2mask = msg[p:p+4]data = msg[p+4:]return ''.join([chr(ord(v) ^ ord(mask[k%4])) for k, v in enumerate(data)])def parse_headers(self, msg):headers = {}header, data = msg.split('\r\n\r\n', 1)for line in header.split('\r\n')[1:]:key, value = line.split(': ', 1)headers[key] = valueheaders['data'] = datareturn headersdef generate_token(self, msg):key = msg + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'ser_key = hashlib.sha1(key).digest()return base64.b64encode(ser_key)#服务端
class websocket_server(threading.Thread):def __init__(self, port):super(websocket_server, self).__init__()self.port = portdef run(self):sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)sock.bind(('0.0.0.0', self.port))sock.listen(5)print 'websocket server started!'while True:connection, address = sock.accept()try:username = "ID" + str(address[1])thread = websocket_thread(connection, username)thread.start()clients[username] = connectionexcept socket.timeout:print 'websocket connection timeout!'if __name__ == '__main__':server = websocket_server(9000) server.start()

注意:这里服务器的ip设置最好设置为0.0.0.0,允许局域网其他计算机访问

网页端代码,用于向安卓端推送消息

<!--
@http://www.cnblogs.com/zhuweisky/p/3930780.html
-->
<!DOCTYPE html>
</html><head><meta charset="utf-8"></head><body><h3>WebSocketTest</h3><div id="login"><div><input id="serverIP" type="text" placeholder="服务器IP" value="127.0.0.1" autofocus="autofocus" /><input id="serverPort" type="text" placeholder="服务器端口" value="9000" /><input id="btnConnect" type="button" value="连接" onclick="connect()" /></div><div><input id="sendText" type="text" placeholder="发送文本" value="I'm WebSocket Client!" /><input id="btnSend" type="button" value="发送" onclick="send()" /></div><div><div>来自服务端的消息</div><textarea id="txtContent" cols="50" rows="10" readonly="readonly"></textarea></div></div></body><script>var socket;function connect() {var host = "ws://" + $("serverIP").value + ":" + $("serverPort").value + "/"socket = new WebSocket(host);try {socket.onopen = function (msg) {$("btnConnect").disabled = true;alert("连接成功!");};socket.onmessage = function (msg) {if (typeof msg.data == "string") {displayContent(msg.data);}else {alert("非文本消息");}};socket.onclose = function (msg) { alert("socket closed!") };}catch (ex) {log(ex);}}function send() {var msg = $("sendText").valuesocket.send(msg);}window.onbeforeunload = function () {try {socket.close();socket = null;}catch (ex) {}};function $(id) { return document.getElementById(id); }Date.prototype.Format = function (fmt) { //author: meizz var o = {"M+": this.getMonth() + 1, //月份 "d+": this.getDate(), //日 "h+": this.getHours(), //小时 "m+": this.getMinutes(), //分 "s+": this.getSeconds(), //秒 "q+": Math.floor((this.getMonth() + 3) / 3), //季度 "S": this.getMilliseconds() //毫秒 };if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));for (var k in o)if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));return fmt;}function displayContent(msg) {$("txtContent").value += "\r\n" +new Date().Format("yyyy/MM/dd hh:mm:ss")+ ":  " + msg;}function onkey(event) { if (event.keyCode == 13) { send(); } }</script>
</html>

安卓端实现

WebSocketClient地址 https://github.com/TooTallNate/Java-WebSocket

导入步骤

  1. 在gradle的repository中添加

    mavenCentral()

  2. 在build中添加

    compile “org.java-websocket:Java-WebSocket:1.3.4”

3.运行gradle同步

利用WebSocket自己手搓一个工具类,放到Service中启动

package com.halfopen.h.cislsign;import android.util.Log;import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;import java.net.URI;
import java.net.URISyntaxException;import static cn.jpush.android.api.JPushInterface.a.s;/*** Created by h on 2017/7/23.*/public class MyWebSocketClient {//WebSocketClient 和 addressprivate WebSocketClient mWebSocketClient;private String address = "ws://10.222.108.43:9000";//初始化WebSocketClient/**** @throws URISyntaxException*/private void initSocketClient() throws URISyntaxException {if(mWebSocketClient == null) {mWebSocketClient = new WebSocketClient(new URI(address)) {@Overridepublic void onOpen(ServerHandshake serverHandshake) {Log.d("flag--","onOpen(WebSocketClient.java:32)-->>"+"成功建立websocket连接");}@Overridepublic void onMessage(String s) {//服务端消息Log.d("flag--","onMessage(WebSocketClient.java:39)-->>"+"收到来自服务器的消息"+s);}@Overridepublic void onClose(int i, String s, boolean remote) {//连接断开,remote判定是客户端断开还是服务端断开Log.d("flag--","onClose(WebSocketClient.java:46)-->>"+"Connection closed by " + ( remote ? "remote peer" : "us" ) + ", info=" + s);closeConnect();}@Overridepublic void onError(Exception e) {Log.d("flag--","onError(WebSocketClient.java:53)-->>"+s);}};}}//连接private void connect() {new Thread(){@Overridepublic void run() {mWebSocketClient.connect();}}.start();}//断开连接private void closeConnect() {try {mWebSocketClient.close();}catch(Exception e) {e.printStackTrace();}finally {mWebSocketClient = null;}}/***发送消息*/private void sendMsg(String msg) {mWebSocketClient.send(msg);}//public void start(){try {initSocketClient();connect();} catch (URISyntaxException e) {e.printStackTrace();}}
}

注意:安卓客户端要和websocekt服务器互通,并且地址和端口要向对应。

参考链接

https://www.zhihu.com/question/20215561
http://blog.csdn.net/icechenbing/article/details/7407588

WebSocket实现android消息推送相关推荐

  1. Android消息推送完美解决方案全析

    Android消息推送完美解决方案全析 参考文章: (1)Android消息推送完美解决方案全析 (2)https://www.cnblogs.com/xueshui20/p/4151405.html ...

  2. Android 消息推送

    Android 消息推送 那位大哥做过啊 android是用服务做吧? pushsharp 雲推送 你要有服務器來服務 不是云推送吧 去搜這個,有server,有client,有demo 自己做的话, ...

  3. android 消息推送方法,一种基于Android系统的消息推送方法技术方案

    [技术实现步骤摘要] 本专利技术涉及一种基于Android系统的消息推送方法,属于计算机 技术介绍 推送功能在手机应用开发中越来越重要,已经成为手机开发的必选项.消息推送,就是在互联网上通过定期传送用 ...

  4. Android—消息推送机制

    知识点: 长连接与短连接 端内与端外推送 通知与透传消息 服务保活(心跳机制) 长连接和短连接 消息推送需要客户端与服务端进行连接,因此分为两种方式 长连接,在TCP层握手成功后,不立即断开连接,并在 ...

  5. Android消息推送 解决方案

    前言 鉴于现在运营需求的增强,消息推送在Android开发中应用的场景是十分常见 如电商的活动宣传.资讯类产品进行新闻推送等等 推送消息截图 今天,我将全面介绍Android中实现消息推送的7种主流解 ...

  6. android消息推送demo

    android消息推送demo 1.消息推送机制  服务器器端需要变被动为主动,通知客户一些开发商认为重要的信息,无论应用程序是否正在运行或者关闭.  我想到了一句话:don't call me,i ...

  7. Android 消息推送OnePush

    Android 消息推送 1.实现原理 1.消息推送的实质 实际上,是当服务器有新消息需推送给用户时,先发送给应用App,应用App再发送给用户 推送的消息一般是用户需要的或app希望用户知道的消息 ...

  8. android消息推送标准,如何提升Android消息推送的到达率?

    消息推送时下已经是app日常运营的重要工具,app的消息推送与一个app的日活息息相关,好的消息推送能够有效地增强用户黏性,然而一切好的消息推送都是建立在能够到达用户终端为前提的,所以消息推送的到达率 ...

  9. 友盟小米收不到推送消息_一个轻量级、可插拔的Android消息推送框架。一键集成推送(极光推送、友盟推送、华为、小米推送等)...

    XPush 一个轻量级.可插拔的Android消息推送框架.一键集成推送(极光推送.友盟推送.华为.小米推送等),提供有效的保活机制,支持推送的拓展,充分解耦推送和业务逻辑,解放你的双手! 在提iss ...

最新文章

  1. 什么是Spring Data?
  2. script标签的for属性和event属性
  3. android零基础教程,Android零基础入门|Activity初入门,创建和配置如此简单
  4. ssm连接mysql引入外部配置文件username无法被正确解析
  5. bootstrap在线定制工具
  6. 美国NIST《可解释的人工智能的四个原则》(全文翻译)
  7. 实验一:线性表的基本操作实现及其应用
  8. 图像相似度比较之哈希算法
  9. 工作一周年,带你认识杭州最好的电商公司
  10. 无源贴片晶振四角引脚_晶振厂家告诉你贴片晶振的脚位方向如何区分 - 中山惠源晶工...
  11. Linux下文件压缩、打包,看这一篇就够了
  12. 清除流氓软件的第一利器(IceSword)
  13. 初步认知Next.js中ISR/RSC/Edge Runtime/Streaming等新概念
  14. 移动新魔百和M302A刷机固件 ty 2G+8G版s905l3线刷包及教程
  15. 【网络游戏植入案例】
  16. [分享]深思--求索人的心智 就是求索长青基业
  17. Mitmproxy代理工具(一):环境配置
  18. php 两个时间戳相隔小时数,php 计算两个时间戳相隔的时间实例
  19. win10系统用什么测试软件,Win10系统如何测试软件兼容性?
  20. word 编辑文章发现 空格变成省略号 换行符什么

热门文章

  1. linux指令_齐南汕
  2. ubuntu 卸载 cuda 以及再次安装
  3. 石油远程《机械设计》第三次在线作业
  4. c语言整数各位数字求和
  5. scratch案例——猜拳游戏
  6. 图扑软件入局工业元宇宙,加速部署数字孪生新生态
  7. 段视频伪原创 手机如何去除视频md5
  8. Java图片流导出图片为黑屏,Matisse预览图片黑屏,Glide内存溢出
  9. Wi-Fi 标准的演进:802.11a b g n ac ax
  10. 计算机考试要手速,【新生入学秘籍NO.1】亲亲,这里建议您赶紧查收学习秘籍哦!...