即时通讯的开源库
目前及时通讯可以使用环信、柔云、腾讯云,这些都是基于TCP连接的,UI也是高度定制的,而且它们的技术也是比较成熟的。
XMPP比较早,是开源的,但是坑也比较多。传输的数据是XML,造成了很多流量的雍余。
数据格式
Socket通讯报文是没有结束标识的,通讯报文保留前8个字节的,给我们字节扩展用的。可以利用这前八个字节做些事情。比如:
我们传一个图片,首先要知道它怎么结束,可以给他一个结束标识,如,“/n/n”。第一个4字节我们可以把图片的总长度传过去,根据这个长度判断ImageDate是否传完。第二个字节可以传它的数据格式,定义为content,用来告诉客户端和服务器端传的是什么。然后再拼接为ImageData,并传送到Action。
代码Demo
#import "ViewController.h"
#import "GCDAsyncSocket.h" static NSString *server_host = @"127.0.0.1";
static const short server_port = ; #define VA_Commadn_id 0x00000001 @interface ViewController ()<GCDAsyncSocketDelegate> @property (strong, nonatomic) GCDAsyncSocket *clientSocket;
@property (weak, nonatomic) IBOutlet UITextField *textField; @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self initGCDAsyncSocket];
} - (void)initGCDAsyncSocket{
//创建 Socket
if (_clientSocket == nil) {
_clientSocket = [[GCDAsyncSocket alloc] initWithDelegate:self
delegateQueue:dispatch_get_main_queue()];
}
} - (BOOL)connect{
NSError *error = nil;
BOOL connectFlag = [_clientSocket connectToHost:server_host onPort:server_port error:&error];
if (error) {
NSLog(@"%@",error);
}
return connectFlag;
} - (void)disConnect{
[_clientSocket disconnect];
} #pragma mark -- GCDAsyncSocketDelegate
//连接成功回调
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{
NSLog(@"连接成功"); [_clientSocket readDataWithTimeout:- tag:];
} //断开连接
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{
NSLog(@"断开连接%@",err.localizedDescription);
} //接受消息
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
NSLog(@"接受到消息");
[_clientSocket readDataWithTimeout:- tag:];
} - (void)sendImage{
//图片数据
UIImage *img = [UIImage imageNamed:@"icon_socket"];
NSData *imgData = UIImagePNGRepresentation(img); NSMutableData *totalData = [NSMutableData data]; //0~3 总长度,前四个字节的总长度 unsigned int totalSize = (int)imgData.length + + ; NSData *totalSizeData = [NSData dataWithBytes:&totalSize length:];
//数据拼接
[totalData appendData:totalSizeData]; // 拼接标识
unsigned int commandId = VA_Commadn_id; NSData *commandIdData = [NSData dataWithBytes:&commandId length:]; [totalData appendData:commandIdData]; //拼接图片数据
[totalData appendData:imgData]; //发送数据
[_clientSocket writeData:totalData withTimeout:- tag:]; } #pragma mark -- Button Action - (IBAction)connectAction:(UIButton *)sender{
[self connect];
} - (IBAction)disConnectAction:(UIButton *)sender{
[self disConnect];
} - (IBAction)sendAction:(UIButton *)sender{
NSData *data = [_textField.text dataUsingEncoding:NSUTF8StringEncoding]; [_clientSocket writeData:data withTimeout:- tag:];
} - (IBAction)sendImageAction:(id)sender {
[self sendImage];
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} @end
使用的第三方库的Podfile:
platform:ios, '9.0' target "002--AsyncSocket" do
pod 'CocoaAsyncSocket'
end
及时通讯绘制图片
即时通讯通过画板来绘图可以将绘制贝塞尔尔曲线的CGPoint点放入一个数组,但是CGPoint点是不能传递过去的,会崩溃的。可以将CGPoint点转化为字典,再传递过去。
心跳机制
简介:
在使用TCP长连接的IM服务设计中,往往都会涉及到心跳。心跳一般是指客户端每隔一定时间向服务端发送自定义指令,以判断双方是否存活,因其按照一定间隔发送,类似于心跳,故称为心跳指令。
003--WebSocket 即时通讯机制 代码片段
- (void)initHeart{
//keepAlive 保证连接存在, 真正可用的 心跳机制验证连接双方是否可用
//心跳包 ------ > 连接双方不可用,主动断开连接
//服务端也是会有,心跳包,主动断开连接
//设置超时间 3分钟(心跳设置3分钟):是因为NAT(与外网和内网有关)的失效时间是3分钟
__weak typeof(self) weakSelf = self;
_heatBeat = [NSTimer scheduledTimerWithTimeInterval:* repeats:YES block:^(NSTimer * _Nonnull timer) {
//具体发送根据实际情况
[weakSelf.socket send:@"heart"];
}];
[[NSRunLoop currentRunLoop] addTimer:_heatBeat forMode:NSRunLoopCommonModes];
}
Ping-Pong 机制
发送消息时会判断连接是否存在。如:
A设备给B设备发送消息,A设备上线他会告诉B设备A设备上线了,会得到服务器的反馈,知道A设备上线了。A设备把数据包丢给B设备,B设备会检测A设备是否在线,如果在线,他会通过A和B之间建的Socket连接发送消息,若B不在线,会走苹果的APNS通道。