1.需求描述
手机端发送组播给iot设备, iot设备根据接收到的组播信息,链接wifi,链接成功后发送广播告诉手机已连接成功
此处只展示实现组播的功能, 发送什么数据, 怎么发送, 发送多少暂时不讨论
2. 准备工作
手机端组播,需要使用UDP, 已有现成的GCDAsyncUdpSocket可用,可以节省一部分工作
3. 砌砖
关于GCDAsyncUdpSocket的使用网上有很多文档,只展示出实现组播功能的一小部分, 当然为了封装成SDK将GCDAsyncUdpSocket 转换成了LZXAsyncUdpSocket 以免项目中再次用到 GCDAsyncUdpSocket 时 冲突
- 初始化
- (LZXAsyncUdpSocket *)udpSocket {
if (_udpSocket == nil) {
dispatch_queue_t DeletageQueue = dispatch_queue_create("DelegateQueue", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t SocketQueue = dispatch_queue_create("SocketQueue", DISPATCH_QUEUE_SERIAL);
// 因为iot对接收的包的顺序有要求,此处使用串行队列执行任务
_udpSocket = [[LZXAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:DeletageQueue socketQueue:SocketQueue];
NSError *error = nil;
[_udpSocket bindToPort:8888 error:&error];
if (error) {
NSLog(@"绑定端口失败");
}
[_udpSocket enableBroadcast:YES error:&error];
if (error) {
NSLog(@"启用广播失败");
}
[_udpSocket beginReceiving:&error];
if (error) {
NSLog(@"启用接受失败");
}
}
return _udpSocket;
}
- 发送数据
NSString *host = [NSString stringWithFormat:@"%lu", ipAddr];
uint16_t port = 8888;//通过端口监测
// 如果拿到的是16进制地址, 需要转换一下
host = [self longToIp:(NSInteger)ipAddr];
[self.udpSocket sendData:data toHost:host port:port withTimeout:10 tag:0];
- 实现代理方法
- (void)udpSocket:(LZXAsyncUdpSocket *)sock didConnectToAddress:(NSData *)address {
// NSLog(@"已经连接");
}
- (void)udpSocket:(LZXAsyncUdpSocket *)sock didNotConnect:(NSError *)error {
// NSLog(@"连接失败");
}
- (void)udpSocket:(LZXAsyncUdpSocket *)sock didSendDataWithTag:(long)tag {
// NSLog(@"发送成功 %ld", tag );
}
- (void)udpSocket:(LZXAsyncUdpSocket *)sock didNotSendDataWithTag:(long)tag dueToError:(NSError *)error {
// NSLog(@"发送失败 %@", error);
}
- (void)udpSocket:(LZXAsyncUdpSocket *)sock didReceiveData:(NSData *)data fromAddress:(NSData *)address withFilterContext:(id)filterContext {
NSString *s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if ([s isEqualToString:@"success"]) {
// 联网成功停止发送,并提示成功
}
}
- (void)udpSocketDidClose:(LZXAsyncUdpSocket *)sock withError:(NSError *)error {
}
5. 注意点
- 接收广播时监听的端口和广播端发送的端口要一致。
- 如果要进行广播/组播数据,必须只能使用[socket bindToPort:54321 error:&error] 方法来绑定端口,不能绑定IP地址并且启用广播,否则不能广播数据。
- 该实例没有被销毁前,只能被创建一次,因为端口正在被使用
6. 其他
- iot设备接收的组播报有同步报、数据报、接收完成报三部分组成,所以配网一次需要发送很多数据报
- 报文之前需要有几毫秒的时间间隔让设备接收反应
- 此次iot设备是根据数据报的长度获取的数据, 跟发送的内容没有关系,所以在使用GCDAsyncUdpSocket时,在其内部单独添加了数据长度的属性已便自己设备数据长度,而不是获取的buffer的长度
- iot设备按顺序接收数据报, 从有序的数据报中解析数据, 所有发送数据报也需要有序发送
7. 参考
单播、组播、广播差别: https://www.cnblogs.com/wzjhoutai/p/6917477.html
GCDAsyncUdpSocket 组播监听端口接收数据 https://blog.csdn.net/nogodoss/article/details/27313043
网友评论