基于WebSocket协议的iOS端即时聊天

好好好久没有在cnblogs上写博客,不过在这里写的最早的一篇博客的时间戳,真是时间久远啊,那时候还没毕业。不在cnblogs的期间,在github pages、简书上写过博客,github pages的markdown还是不错的,不过百度不能检索到文章,也就是通过百度,永远无法导流搜索到我的文章(感动moving),简书感觉更适合抒情鸡汤,可能我不太能融入那个用户群体。不过现在我回来了,那些在github pages上的文章,我暂时也不迁移了,毕竟人生本来就不完美,提醒自己不能有强迫症(内心默念三次)。续上上一篇博客的时间(2016-04-29)继续回到这里,中间的间隔两年多,甚至更长。这段空白时间的大概情况介绍完了~

---------------------脏兮兮的分割线---------------------

言归正传,最近因为公司产品的需要,计划在移动端开发即时聊天的通讯功能。即时聊天的第三方SDK供应商也是非常多的,因为项目高度的自由定制性,数据隐私等方面的考虑,最终Server-Client端都由自己来实现,服务端采用worker man的PHP socket服务器架构。

在长连接双向通信上,选择的是WebSocket协议。开发主要负责iOS Client端的开发,按照开发第三方SDK的标准,将关键的部分封装起来,只留出必要的API供外部调用,将相关代码模块化,方便后期向公司其他项目中移植聊天模块。(不能自己坑自己,遇到移植的需求的可能性是非常大的,所以与其散漫的写代码,不如按照SDK的标准去做开发。)

WebSocket

WebSocket 协议在2008年诞生,2011年成为国际标准。WebSocket 协议本质上是一个基于 TCP 的协议。是建立在 TCP 协议之上的全双工通讯协议,与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器,所以服务器端的实现比较容易。协议标识符是ws,请求地址格式:ws://example.com:80/path

握手过程:

为了建立一个 WebSocket 连接,客户端首先要向服务器发起一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息。如下所示:

客户端请求Header:

1 --- request header ---
2 GET /chat HTTP/1.1
3 Upgrade: websocket
4 Connection: Upgrade
5 Host: 127.0.0.1:8001
6 Origin: http://127.0.0.1:8001
7 Sec-WebSocket-Key: hj0eNqbhE/A0GkBXDRrYYw==
8 Sec-WebSocket-Version: 13

其中附加头信息"Upgrade: WebSocket"表明这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息,根据Sec-WebSocket-Key的字符串,通过sha1算法处理,将response信息(sec-Websocket-Accept字符串)返回给客户端,客户端能成功解码字符串,就和服务器端的 WebSocket连接就建立起来了。

服务器的Response:

1 HTTP/1.1 101 Switching Protocols
2 Content-Length: 0
3 Upgrade: websocket
4 Sec-Websocket-Accept: ZEs+c+VBk8Aj01+wJGN7Y15796g=
5 Server: TornadoServer/4.5.1
6 Connection: Upgrade
7 Date: Wed, 21 Jun 2017 03:29:14 GMT

双方就可以通过这个连接通道自由的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。

使用封装Websocket的SocketRocket(Objective-C)

上面是WebSocket握手连接通信,而站在巨人的肩膀上,这里使用的是Github上facebook的SocketRocket项目,这是关于WebSocket的Objective-C的封装,提供简单的API,让开发者不用去跟底层协议打交道,而是关注于链路上的数据处理,逻辑层。关于SocketRocket的Features使用等,在Github上有详细介绍,使用起来也非常简单。需要注意SRWebSocketDelegate协议的相关方法:

 //当收到服务器的Message时调用,这里的message是id类型,可以是NSString,也可以是NSData。

- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message;

//当与服务器建立连接时调用

- (void)webSocketDidOpen:(SRWebSocket *)webSocket;   

//当发生未知错误的时调用,可能是网络原因等

- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error;

//当关闭WebSocket时调用

- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean;

//接收到服务器的Pong时调用

- (void)webSocket:(SRWebSocket *)webSocket didReceivePong:(NSData *)pongPayload;

//返回YES表示对messages进行转换,以NSString的形式发送,返回NO,表示跳过NSData->NSString的转换,直接以NSData来传递。默认YES

- (BOOL)webSocketShouldConvertTextFrameToString:(SRWebSocket *)webSocket;

使用方式与之前学Java时使用的socket通讯类似,大概流程如下所示:init websocket -> open ->  connected -> sendMsg -> handle server response -> close

具体的代码也是非常容易在网上找到的,就不大段的贴代码了。

上述的通道握手建立并且能与服务器简单通信后,就要考虑各种情况的处理,包括断网,信号差等,就需要考虑断线重连,发送心跳包确定是否与服务器保持着连接的状态。

这里心跳包的发送是定时执行的,使用NSTimer的方式。

 1 dispatch_main_async_safe(^{
 2
 3         [self destoryHeartBeat];
 4
 5         __weak typeof(self) weakSelf = self;
 6         //心跳设置为3分钟,NAT超时一般为5分钟
 7         _heartBeat = [NSTimer scheduledTimerWithTimeInterval:3 * 60 repeats:YES block:^(NSTimer * _Nonnull timer) {
 8             NSLog(@"heart");
 9             //和服务端约定好发送什么作为心跳标识,尽可能的减小心跳包大小
10             [weakSelf sendHeartBeatMessage];
11         }];
12         [[NSRunLoop currentRunLoop]addTimer:_heartBeat forMode:NSRunLoopCommonModes];
13     })

错误断网等重连的实现:

 1 - (void)reConnect {
 2
 3     [self stopSocket];
 4
 5     if (_connectInterval < 2) {
 6         _connectInterval = 2;
 7     }else{
 8         _connectInterval = _connectInterval + 2;
 9     }
10
11     // 断开连接后每过n+2秒后重新建立一次连接
12     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_connectInterval * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
13         [self startSocket];
14     });
15 }

一个好的与服务器连接的Websocket模块需要细细的打磨,这里展示的都是很粗糙的模块,需要根据以后的需求,出现的问题进行不断的修正,才能有一个好用的Websocket模块。想到了一句话:细节决定成败。所以打磨好生活工作学习中的每一个细节~

原文地址:https://www.cnblogs.com/vokie/p/9007003.html

时间: 2024-11-10 15:08:57

基于WebSocket协议的iOS端即时聊天的相关文章

使用JMeter测试基于WebSocket协议的服务

使用JMeter测试基于WebSocket协议的服务 :first-child{margin-top:0!important}img.plugin{box-shadow:0 1px 3px rgba(0,0,0,.1);border-radius:3px}iframe{border:0}figure{-webkit-margin-before:0;-webkit-margin-after:0;-webkit-margin-start:0;-webkit-margin-end:0}kbd{bord

Jmeter对基于websocket协议的压力测试

WebSocket protocol 是HTML5一种新的协议.它实现了浏览器与服务器全双工通信(full-duplex). 浏览器和服务器只需要要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道.两者之间就直接可以数据互相传送.在此WebSocket 协议中,为我们实现即时服务带来了两大好处: 1. Header  互相沟通的Header是很小的-大概只有 2 Bytes 2. Server Push 浏览器请求 GET /WebSocket/LiveVideo HTTP/1.1

基于TCP协议的服务器中转简易聊天

项目比较简单:主要使用了TCP传输协议.多线程和swing窗口,以及IO流读写. 功能:各窗口之间简单的收发信息,另外附加一个抖动的效果. 服务器代码: 1 package com.java; 2 3 import java.awt.Dimension; 4 import java.awt.Toolkit; 5 import java.awt.event.ActionEvent; 6 import java.awt.event.ActionListener; 7 import java.awt.

基于XMPP协议的手机多方多端即时通讯方案

目   录 基于XMPP协议的手机多方多端即时通讯方案................................................................. 1 目   录.................................................................................................................... 2 一. 开发背景........................

游戏网络编程(三)——WebSocket入门及实现自己的WebSocket协议

(一)WebSocket简介 短连接:在传统的Http协议中,客户端和服务器端的通信方式是短连接的方式,也就是服务器端并不会保持一个和客户端的连接,在消息发送后,会断开这个连接,客户端下次通信时,必须再建立和服务器的新连接,这就是短连接.在短链接的情况下,客户端必须不停的主动发起请求,而服务器始终被动的响应请求,来推送回数据.这种方式用到游戏开发中,显然是不适合的. 长连接:那么与之相对的就是长连接了.在长连接的情况下,客户端和服务器端始终保持一条有效的连接,那么客户端并不需要不停的主动发送消息

Node.js + Web Socket 打造即时聊天程序嗨聊

前端一直是一块充满惊喜的土地,不仅是那些富有创造性的页面,还有那些惊赞的效果及不断推出的新技术.像node.js这样的后端开拓者直接将前端人员的能力扩大到了后端.瞬间就有了一统天下的感觉,来往穿梭于前后端之间代码敲得飞起,从此由前端晋升为'前后端'. 图片来自G+ 本文将使用Node.js加web socket协议打造一个网页即时聊天程序,取名为HiChat,中文翻过来就是'嗨聊',听中文名有点像是专为寂寞单身男女打造的~ 其中将会使用到express和socket.io两个包模块,下面会有介绍

基于TCP协议的简单Socket通信笔记(JAVA)

好久没写博客了,前段时间忙于做项目,耽误了些时间,今天开始继续写起~ 今天来讲下关于Socket通信的简单应用,关于什么是Socket以及一些网络编程的基础,这里就不提了,只记录最简单易懂实用的东西. 1.首先先来看下基于TCP协议Socket服务端和客户端的通信模型: Socket通信步骤:(简单分为4步) 1.建立服务端ServerSocket和客户端Socket 2.打开连接到Socket的输出输入流 3.按照协议进行读写操作 4.关闭相对应的资源 2.相关联的API: 1.首先先来看下S

Java中基于UDP协议的的网络编程(基础篇)

---恢复内容开始--- 一:什么是网络编程? 通俗的来说, 网络编程就是编写程序,让联网的两个或多个设备(例如计算机)之间进行数据传输.Java语言也支持网络编程,JDK提供的 java.net包提供了很多于网络编程相关的类,来支持网络编程方面的学习. 二:java网络编程所使用的协议? 有了计算机网络的基础,我们不难理解,在java中,网络编程是基于网络传输协议的. java网络编程,可以是基于TCP协议的,也可以基于UDP协议的.那么首先我们得知道tcp协议和udp两种协议的区别. 区别:

iOS通过SocketRocket实现websocket的即时聊天

之前公司的即时聊天用的是常轮循,一直都觉得很不科学,最近后台说配置好了socket服务器,我高兴地准备用asyncsocket,但是告诉我要用websocket,基于HTML5的,HTML5中提出了一种新的双向通信协议--WebSocket,本文尝试采用这种技术来实现以上的实时聊天功能. 在搜索了很多资料后,用square大神的SocketRocket进行实现,会比较简单,同时URL和端口,发送消息参数需要和后台约定好. 首先pod导入SocketRocket platform :ios, '7