基于WebSocket构建移动端实时应用

移动开发
对于传统的网络应用,大部分情况下使用的是Http短连接,这意味着你发送一次请求,服务器给你返回响应信息,然后连接就被断掉了。然而现实生活 中,很多应用实际上是需要一种实时机制的支持,比如微信,你就需要实时收到对方发送的回复信息。

前言

对于传统的网络应用,大部分情况下使用的是Http短连接,这意味着你发送一次请求,服务器给你返回响应信息,然后连接就被断掉了。然而现实生活 中,很多应用实际上是需要一种实时机制的支持,比如微信,你就需要实时收到对方发送的回复信息。对于应用处于后台的情况下,你可以使用系统级别的推送服 务,比如iOS下的APNS和Android下的GCM。应用处于前台时呢,则需要自己去和服务端建立一个Http长连接或者轮询,这种方式对于服务器的性能要求还是比较高的。HTML5中提出了一种新的双向通信协议--WebSocket,本文尝试采用这种技术来实现以上的实时推送功能。

WebSocket

WebSocket是HTML5开始提供的一种在客户端和服务器间持久连接的双向通信网络技术。 WebSocket通信协议于2011年被IETF定为标准 RFC 6455,WebSocketAPI被W3C定为标准。协议本身使用新的ws://URL格式,但它是在标准HTTP上实现的。通过使用HTTP和 HTTPS端口,它避免了从Web代理后的网络连接站点时引入的各种问题。HTML5规范不只描述了协议本身,还描述了使用WebSocket编写客户端 代码所需要的浏览器API。在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

服务端实现

服务端采用了Facebook开源的Tornado框架,由于Tornado原生支持WebSocket协议,用它来实现服务端非常方便。

Tornado在WebSocket模块中提供了一个WebSocketHandler类。这个类提供了和已连接的客户端通信的WebSocket 事件和方法的钩子。当一个新的WebSocket连接打开时,open方法被调用,而on_message和on_close方法分别在连接接收到新的消 息和客户端关闭时被调用。

此外,WebSocketHandler类还提供了write_message方法用于向客户端发送消息,close方法用于关闭连接。

以开关状态改变检测为例,服务端部署的代码如下:

  1. class Switch(BaseModel): 
  2.     __tablename__ = 'switch'       
  3.  
  4.     id = Column(Integer, primary_key = True) 
  5.     name = Column(String(30)) 
  6.     status = Column(Boolean, server_default = text('False')) #开关当前状态 
  7.     level = Column(Integer)                                  #最小可操作等级 
  8.  
  9.     callbacks = [] 
  10.     @classmethod 
  11.     def register(cls, callback): 
  12.         cls.callbacks.append(callback) 
  13.  
  14.     @classmethod 
  15.     def unregister(cls, callback): 
  16.         cls.callbacks.remove(callback) 
  17.  
  18.     def notifyCallbacks(self): 
  19.         for callback in self.callbacks: 
  20.             callback(self.id,self.status) 

以上是封装的开关对象,使用了SQLAlchemy作为ORM,其中BaseModel是继承自declarative_base。 定义了两个类方法,分别是注册和移除回调,另外一个实例方法来通知回调。

对外处理请求的handler:

  1. class GetSwitchStatusHandler(BaseWebsockHandler): 
  2.  
  3.     def open(self): 
  4.         Switch.register(self.callback) 
  5.  
  6.     def on_close(self): 
  7.         Switch.unregister(self.callback) 
  8.              
  9.     def on_message(self,msg): 
  10.         pass 
  11.  
  12.     def callback(self,switch_id,status): 
  13.         self.write_message('{"switch_id":"%s","status":"%d"}'%(switch_id,status)) 

BaseWebsockHandler继承自tornado.websocket.WebSocketHandler,在initialize中对于SQLAlchemy的session进行了初始化

由于在本例中不需要取客户端的上行消息,故直接pass调了on_message方法。callback方法则用来处理回调,将改变后的开关信息返回给客户端。

客户端实现

客户端使用了Square开源的SocketRocket

在iOS工程中安装可以直接使用源码,也可以用CocoaPods安装,将以下依赖加入到PodFile中,再执行install命令即可

pod 'SocketRocket', '~> 0.3.1-beta2'

SocketRocket的核心是SRWebSocket这个类,需要在使用WebSocket连接的ViewController中实现SRWebSocketDelegate。

  1. - (void)connect{ 
  2.      
  3.     webSocket.delegate = nil; 
  4.     [webSocket close];  
  5.     webSocket = [[SRWebSocket alloc] initWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:SWITCH_STATUS_URL]]]; 
  6.     webSocket.delegate = self; 
  7.     NSLog(@"Opening Connection..."); 
  8.     [webSocket open]; 
  9.  
  10. ··· 
  11.  
  12. pragma mark - SRWebSocketDelegate 
  13.  
  14. - (void)webSocketDidOpen:(SRWebSocket *)webSocket;{ 
  15.     NSLog(@"Websocket Connected"); 
  16.  
  17. - (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error;{ 
  18.     NSLog(@":( Websocket Failed With Error %@", error); 
  19.     webSocket = nil; 
  20.  
  21. - (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message;{ 
  22.     NSLog(@"Received \"%@\"", message); 
  23.  
  24. - (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean;{ 
  25.     NSLog(@"WebSocket closed"); 
  26.     webSocket = nil; 

把delegate指向自身,然后调用SRWebSocket中的方法发送请求即可。 收到下行消息会调用didReceiveMessage这个方法,如果需要在请求时携带参数,可以用类似get请求的方法,将请求放在url字符串中。

到此为止WebSocket的基本功能就实现完毕了,完整demo可以参考我的Github

原文地址

责任编辑:徐川 来源: blog
相关推荐

2016-07-29 13:47:05

RethinkDBWeb

2024-03-19 08:45:45

WebSocketSpring应用开发

2017-11-03 15:05:56

Storm数据处理服务器

2014-06-10 13:54:05

Node.jsSocket.IOWebSocket

2021-07-13 07:04:19

Flink数仓数据

2017-09-26 09:35:22

2014-07-18 09:59:17

移动webJavascript移动Web

2024-09-30 11:45:10

2024-06-12 08:46:19

2021-08-31 10:18:34

Flink 数仓一体快手

2013-03-28 14:54:36

2023-08-16 14:39:20

微服务Java

2023-06-09 13:07:56

Web机器学习浏览器

2014-07-07 11:33:50

SaaSNew Relic移动开发

2014-12-04 14:10:22

移动应用云

2013-04-01 09:35:30

移动云应用BYOD云模型

2022-07-26 14:53:10

WebSocket网络通信协议

2017-01-19 17:37:00

iOS移动端架构设计

2022-07-27 17:40:47

技术人脸识别移动

2014-07-21 10:56:16

web CMSJavascriptjQuery插件
点赞
收藏

51CTO技术栈公众号