上回我们说到心跳消息,当我们收到Server返回来的第一条心跳消息时,就可以向Server发一条,请求在线用户列表的协议,请求协议非常的简单,同心跳消息一样只有消息头,不同的是它的MessageType是112。当Server收到这条请求协议后,会回复一条MessageType同样为112的回复消息,与请求协议不同,回复协议带有Body体。下面让我们来看一条Server回复Client在线列表的byte流:
00000000 FF FF 70 00 02 00 00 00 18 00 00 00 02 5F 30 00 p..... ....._0. 00000010 00 00 00 00 00 00 00 00 04 61 61 30 32 00 00 00 ........ .aa02... 00000020 00 00 00 00 14 00 00 00 02 00 00 00 04 00 00 00 ........ ........ 00000030 61 61 30 32 04 00 00 00 61 61 30 31 aa02.... aa01 |
在ESFramewrok中,所有的消息头都的特征都是相同的。消息头的长度都为36,这里我们只看消息体,MessageBody最开始的是14 00 00 00 ,这是一个int类型的变量,它用来标记在它后面用于描述装载在线用户信息列表的Byte流的长度。跟在它后面的四个字节也是一个int型的变量,它用于标记在线用户的个数,在本列中是02 00 00 00,表明有2个在线用户。在它后面是由一个int型变量和一个String组成的一个小结构体,分别是UserID的长度,和UserID的字符串。有了这些信息,我们就可以解析它,获取在线用户列表,实现代码如下:
int taget = 44;
//获取在线用户个数
int userNume;
[data getBytes:&userNume range:NSMakeRange(40, 4)];
for (int i =0 ; i<userNume; i++) {
int userIDLengh;
[data getBytes:&userIDLengh range:NSMakeRange(taget, 4)];
taget = taget + 4;
NSString* userID = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(taget, userIDLengh)] encoding:NSASCIIStringEncoding];
taget = taget + userIDLengh;
//这里我把通过解析得到的userID装到了一个NSMutableArray的变量里
[appData.onLineUserArray addObject:userID];
}
//成功解析后,我们要刷新用于显示在线列表的UITableView
[appData refreshOnLineUserList];
上面的refreshOnLineUserList存在于RapidEngineDemoAppDelegate.m中,在此方法中我让它触发了一个事件,使侦听这个事件的在线列表Table去更新它的内容。之前我们提到过,两个类之间的通信,可以通过实现对方的协议方法,去实现。这里我们用到了另外一种方法,即观察者模式。在Foundation.framework已有现成的NSNotification帮我们实现了观察者模式。要使用它需以下步骤:
1.预订事件,在本例中要显示用户列表的类是ChatViewController,我们在它的初始化方法中加入下面的代码去预订这个事件
appData = [[UIApplication sharedApplication] delegate];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onFefreshOnLineUserList:) name:@"FefreshOnLineUserList" object:appData];
appData 即是RapidEngineDemoAppDelegate的对象,这里我们可以把它看成是一个单件,可以用sharedApplication去获取它。上面的代码就是说ChatViewController侦听了appData的一个名为“FefreshOnLineUserList”的事件,一但这个事件触发了,它就会去调用自己的onFefreshOnLineUserList方法。
下面是onFefreshOnLineUserList方法的实现,它跟新了tableView中的数据
-(void)onFefreshOnLineUserList:(NSNotification *)notification{
[self.tableView reloadData];
}
2.触发事件,在本例中触发事件的命令在RapidEngineDemoAppDelegate中,如下:
-(void)refreshOnLineUserList{
[[NSNotificationCenter defaultCenter] postNotificationName:@"FefreshOnLineUserList"
object:self
userInfo:nil];
}