iOS --- UDP

2018-11-06  本文已影响0人  BabyNeedCare

想起西游记里的一个场景:

孙悟空拿了真的葫芦,问银角大王,我叫你名字,你敢答应吗?银角大王应答了,结果,悲催的被吸走了。

UDP协议广播机制:

原理一样。在人群叫喊(广播)银角大王。银角大王应答。抓的就是你,哈哈!!!

UDP广播机制的应用场景:

例如:iPhone手机连接设备,例如手环。

  1. 100个iPhone同时叫喊(广播)手环,手环应答,某一台iPhone设备就连接,然后进入长连接(如果有同学问为啥是长连接,不是长连接难不成一连接就断开?)

  2. 手环监听人体运动信息,iPhone连接后,就可以通过发送指令获取已经存储的信息 / 写入消息,展示在iPhone UI上

AsyncSocket流程有4步:

1.创建socket,修改配置(允许广播形式)

+(Singleton *)sharedInstance{
    static Singleton *sharedInstace = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstace = [[self alloc]init];
    });
    return sharedInstace;
}//一个客户端只进行一条socket的连接,所以这里使用了单例。

self.socket = [[AsyncUdpSocket alloc]initWithDelegate:self]; //创建socket(UDP)

[self.socket enableBroadcast:YES error:nil];   //允许广播形式

2.绑定本地IP

self.localhost = [self getIPAddress];

NSError *error = nil;

[self.socket bindToAddress:self.localhost port:0 error:&error];  //绑定本地IP与端口
-(NSString *)getIPAddress{
    NSString *address = @"error";
    struct ifaddrs *interface = NULL;
    struct ifaddrs *temp_addr = NULL;
    int success = 0;
    
    success = getifaddrs(&interface);
    if(success == 0){
        temp_addr = interface;
        while (temp_addr != NULL) {
            if(temp_addr->ifa_addr->sa_family == AF_INET){
                
                
                //if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]){
                address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
                // }
            }
            temp_addr = temp_addr->ifa_next;
        }
    }
    freeifaddrs(interface);
    return address;
}//本地IP的获取方法

3.向服务器发送包

-(void)longConnectToSocket{
    NSData *dataStream = [message dataUsingEncoding:NSUTF8StringEncoding];
    [self.socket sendData:dataStream
                   toHost:@"x.x.x.x"
                     port:YourPort
              withTimeout:-1
                      tag:0];
}//端口是固定的, ip嵌入式提供

4.接收包

-(void)onUdpSocket:(AsyncUdpSocket *)sock didSendDataWithTag:(long)tag{
    [self.socket receiveWithTimeout:-1 tag:tag];
}

-(BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port{
    do some thing about data
    return YES;
}

用得比较多的可能是GCDAsyncUdpSocket。

处理方式与AsyncSocket大致相同。

  1. import "GCDAsyncUdpSocket.h"

  2. 遵守协议<GCDAsyncUdpSocketDelegate>
  3. 声明一个属性@property (strong, nonatomic)GCDAsyncUdpSocket * udpSocket;
  4. 创建Socket
_udpSocket = [[GCDAsyncUdpSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_main_queue()];

5.监听接口&接收数据

    NSError * error = nil;
    [_udpSocket bindToPort:udpPort error:&error];
    if (error) {//监听错误打印错误信息
        NSLog(@"error:%@",error);
    }else {//监听成功则开始接收信息
        [_udpSocket beginReceiving:&error];
    }

  1. 发送数据
[_udpSocket sendData:sendData toHost:ipAddress port:udpPort withTimeout:-1 tag:0];

  1. GCDAsyncUdpSocket代理方法
//看看发送数据结果
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didSendDataWithTag:(long)tag{
    NSLog(@"发送信息成功");
}

- (void)udpSocket:(GCDAsyncUdpSocket *)sock didNotSendDataWithTag:(long)tag dueToError:(NSError *)error{
    NSLog(@"发送信息失败");
}

//发送成功就该接收数据了
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data fromAddress:(NSData *)address withFilterContext:(id)filterContext{
    NSLog(@"接收到%@的消息:%@",address,data);//自行转换格式吧
}

接收信息有两种方法:
1.[_udpSocket receiveOnce:&error]此方法是一条一条数据接收,用途往往是先发广播,接收到信息后使用TCP进行长连接,故只接收一条数据即可。
2.[_udpSocket beginReceiving:&error]此方法是持续接收,像微信是,自然是要持续接收信息,故使用此方法进行接收数据。

上一篇 下一篇

猜你喜欢

热点阅读