• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
Harley
博客园    首页    新随笔    联系   管理    订阅  订阅

即时通讯(III)

即时通讯的开源库

 

 目前及时通讯可以使用环信、柔云、腾讯云,这些都是基于TCP连接的,UI也是高度定制的,而且它们的技术也是比较成熟的。

XMPP比较早,是开源的,但是坑也比较多。传输的数据是XML,造成了很多流量的雍余。

数据格式

 

  Socket通讯报文是没有结束标识的,通讯报文保留前8个字节的,给我们字节扩展用的。可以利用这前八个字节做些事情。比如:

  我们传一个图片,首先要知道它怎么结束,可以给他一个结束标识,如,“/n/n”。第一个4字节我们可以把图片的总长度传过去,根据这个长度判断ImageDate是否传完。第二个字节可以传它的数据格式,定义为content,用来告诉客户端和服务器端传的是什么。然后再拼接为ImageData,并传送到Action。

 

代码Demo

  1 #import "ViewController.h"
  2 #import "GCDAsyncSocket.h"
  3 
  4 static NSString *server_host = @"127.0.0.1";
  5 static const short server_port = 6969;
  6 
  7 #define VA_Commadn_id 0x00000001
  8 
  9 @interface ViewController ()<GCDAsyncSocketDelegate>
 10 
 11 @property (strong, nonatomic) GCDAsyncSocket *clientSocket;
 12 @property (weak, nonatomic) IBOutlet UITextField *textField;
 13 
 14 @end
 15 
 16 @implementation ViewController
 17 
 18 - (void)viewDidLoad {
 19     [super viewDidLoad];
 20     // Do any additional setup after loading the view, typically from a nib.
 21     [self initGCDAsyncSocket];
 22 }
 23 
 24 - (void)initGCDAsyncSocket{
 25     //创建 Socket
 26     if (_clientSocket == nil) {
 27         _clientSocket = [[GCDAsyncSocket alloc] initWithDelegate:self
 28                                                    delegateQueue:dispatch_get_main_queue()];
 29     }
 30 }
 31 
 32 - (BOOL)connect{
 33     NSError *error = nil;
 34     BOOL connectFlag = [_clientSocket connectToHost:server_host onPort:server_port error:&error];
 35     if (error) {
 36         NSLog(@"%@",error);
 37     }
 38     return connectFlag;
 39 }
 40 
 41 - (void)disConnect{
 42     [_clientSocket disconnect];
 43 }
 44 
 45 #pragma mark -- GCDAsyncSocketDelegate
 46 //连接成功回调
 47 - (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{
 48     NSLog(@"连接成功");
 49     
 50     [_clientSocket readDataWithTimeout:-1 tag:0];
 51 }
 52 
 53 //断开连接
 54 - (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{
 55     NSLog(@"断开连接%@",err.localizedDescription);
 56 }
 57 
 58 //接受消息
 59 - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
 60     NSLog(@"接受到消息");
 61     [_clientSocket readDataWithTimeout:-1 tag:0];
 62 }
 63 
 64 - (void)sendImage{
 65     //图片数据
 66     UIImage *img = [UIImage imageNamed:@"icon_socket"];
 67     NSData *imgData = UIImagePNGRepresentation(img);
 68     
 69     NSMutableData *totalData = [NSMutableData data];
 70     
 71     //0~3  总长度,前四个字节的总长度
 72     
 73     unsigned int totalSize = (int)imgData.length + 4 + 4;
 74     
 75     NSData *totalSizeData = [NSData dataWithBytes:&totalSize length:4];
 76     //数据拼接
 77     [totalData appendData:totalSizeData];
 78     
 79     // 拼接标识
 80     unsigned int commandId = VA_Commadn_id;
 81     
 82     NSData *commandIdData = [NSData dataWithBytes:&commandId length:4];
 83     
 84     [totalData appendData:commandIdData];
 85     
 86     //拼接图片数据
 87     [totalData appendData:imgData];
 88     
 89     //发送数据
 90     [_clientSocket writeData:totalData withTimeout:-1 tag:0];
 91     
 92 }
 93 
 94 
 95 #pragma mark -- Button Action
 96 
 97 - (IBAction)connectAction:(UIButton *)sender{
 98     [self connect];
 99 }
100 
101 - (IBAction)disConnectAction:(UIButton *)sender{
102     [self disConnect];
103 }
104 
105 - (IBAction)sendAction:(UIButton *)sender{
106     NSData *data = [_textField.text dataUsingEncoding:NSUTF8StringEncoding];
107     
108     [_clientSocket writeData:data withTimeout:-1 tag:0];
109 }
110 
111 - (IBAction)sendImageAction:(id)sender {
112     [self sendImage];
113 }
114 
115 
116 - (void)didReceiveMemoryWarning {
117     [super didReceiveMemoryWarning];
118     // Dispose of any resources that can be recreated.
119 }
120 
121 
122 @end
View Code

使用的第三方库的Podfile:

1 platform:ios, '9.0'
2 
3 target "002--AsyncSocket" do
4     pod 'CocoaAsyncSocket'
5 end
View Code

 

及时通讯绘制图片

  即时通讯通过画板来绘图可以将绘制贝塞尔尔曲线的CGPoint点放入一个数组,但是CGPoint点是不能传递过去的,会崩溃的。可以将CGPoint点转化为字典,再传递过去。

 

 

心跳机制

简介:

在使用TCP长连接的IM服务设计中,往往都会涉及到心跳。心跳一般是指客户端每隔一定时间向服务端发送自定义指令,以判断双方是否存活,因其按照一定间隔发送,类似于心跳,故称为心跳指令。

003--WebSocket 即时通讯机制 代码片段

 1 - (void)initHeart{
 2   //keepAlive   保证连接存在, 真正可用的  心跳机制验证连接双方是否可用
 3  //心跳包 ------ > 连接双方不可用,主动断开连接
 4 //服务端也是会有,心跳包,主动断开连接
 5     //设置超时间  3分钟(心跳设置3分钟):是因为NAT(与外网和内网有关)的失效时间是3分钟
 6     __weak typeof(self) weakSelf = self;
 7     _heatBeat = [NSTimer scheduledTimerWithTimeInterval:3*60 repeats:YES block:^(NSTimer * _Nonnull timer) {
 8         //具体发送根据实际情况
 9         [weakSelf.socket send:@"heart"];
10     }];
11     [[NSRunLoop currentRunLoop] addTimer:_heatBeat forMode:NSRunLoopCommonModes];
12 }
View Code

 

 

 

Ping-Pong 机制

  发送消息时会判断连接是否存在。如:

A设备给B设备发送消息,A设备上线他会告诉B设备A设备上线了,会得到服务器的反馈,知道A设备上线了。A设备把数据包丢给B设备,B设备会检测A设备是否在线,如果在线,他会通过A和B之间建的Socket连接发送消息,若B不在线,会走苹果的APNS通道。

 

 

 WebSocket协议(数据帧格式)

 

posted @ 2018-06-17 21:22  Harely  阅读(280)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3