zoukankan      html  css  js  c++  java
  • 先UDP组播 socket 再TCP建立长连接

    相关概念:
        单播、多播(组播)和广播的区别  http://blog.csdn.net/wangerge/article/details/3931491
        多播(组播)地址范围--224.0.0.0到239.255.255.255
        广播地址: 255.255.255.255

    应用场景:
         家庭局域网设备组件一个局域网,各设备提供udp socket监听服务,手机客户端进入此局域网,并向局域网内发送组播或广播,对应设备响应组播并按需要与手机端建立tcp长连接通信


    1.服务端:
      - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
    {

        GCDAsyncUdpSocket *serverSocket = [[[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()] autorelease];
        NSError *bindError = nil;
        //bindToPort绑定端口函数,只能使用在充当server 的socket上 client socket不能使用
        //[serverSocket bindToPort:8099 interface:@"en1" error:&bindError]; //en1 随机分配的ip地址
        [serverSocket bindToPort:8099 error:&bindError]; //该socket默认绑定到该机子网卡的ip地址
        if (bindError) {
            NSLog(@"bindError = %@",bindError);
        }
       
        NSError *receiveError = nil;
        [serverSocket beginReceiving:&receiveError]; //开始接收数据,一定要否则后面无法接收数据 不接收数据时调用pauseReceiving
        if (receiveError) {
            NSLog(@"receiveError = %@",receiveError);
        }
        //[serverSocket joinMulticastGroup:@"224.0.1.23" error:nil];//该socket加入到组播224.0.1.23中,之后只要客户端socket向这个组播地址发消息,该socket都能收到 与客户端的发送地址必须一致才能接收
        NSLog(@"%@",[serverSocket localHost]);

       ///////////////////////////服务开启时同时开启TCP服务监听,以便后面建立TCP连接
        GCDAsyncSocket *socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
        NSError *err = nil;
        if(![socket acceptOnPort:8099 error:&err])//tcp socket的监听端口必须要与udp socket的端口一样 后面客户端才能正确与服务端建立tcp连接,因为客户端到时获取的端口是udp socket的端口
        {
            NSLog(@"err.description = %@",err.description);
        }else
        {
            NSLog(@"%@",[NSString stringWithFormat:@"开始监听%d端口.",8099]);
        }
    /////////////////////////////
    }

    udpsocket的关键回调方法:接收到客户端socket发送的消息响应如下
    - (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
          fromAddress:(NSData *)address
    withFilterContext:(id)filterContext {

       NSLog(@"sock = %@, ReceiveData = %@, fromAddress = %@",sock,[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding],[[NSString alloc] initWithData:address encoding:NSUTF8StringEncoding]);
        NSString *responseMessage = @"已即受到";
        NSString *host = nil;
        uint16_t port = 0;
        [GCDAsyncUdpSocket getHost:&host port:&port fromAddress:address];//可获取客户端socket的ip和端口,不过直接打印address是空的
       
        NSLog(@"Adress = %@ %i",host,port);
        [sock sendData:[responseMessage dataUsingEncoding:NSUTF8StringEncoding] toAddress:address withTimeout:-1 tag:10];//服务端回应客户端
       
    }

    Tcp socket关键回调方法
    - (void)socket:(GCDAsyncSocket *)sender didAcceptNewSocket:(GCDAsyncSocket *)newSocket
    {
        NSLog(@"%@",[NSString stringWithFormat:@"建立与%@的连接",newSocket.connectedHost]);
        s = newSocket;
        s.delegate = self;
        [s readDataWithTimeout:-1 tag:0];//必须调用
    }

    -(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
    {
        NSString *receive = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"%@",[NSString stringWithFormat:@"%@:%@",sock.connectedHost,receive]);
       
        NSString *reply = [NSString stringWithFormat:@"收到:%@",receive];
       
        [s writeData:[reply dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
        [s readDataWithTimeout:-1 tag:0];
    }

    2.客户端
       - (IBAction)broadCast:(id)sender {
        GCDAsyncUdpSocket *udpSocket = [[[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()] autorelease];
       
        NSError *error = nil;
        [udpSocket enableBroadcast:YES error:&error];//允许广播 必须 否则后面无法发送组播和广播
        NSString *message = @"ttt";
        //[udpSocket sendData:[message dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:10];//该函数只能用户已经连接的socket
        [udpSocket sendData:[message dataUsingEncoding:NSUTF8StringEncoding] toHost:@"224.0.1.23"   port:8099 withTimeout:-1 tag:10];//客户端socket发送组播或是广播 根据host的ip地址来订
        [udpSocket beginReceiving:nil];//必须要  开始准备接收数据
    }


    UDP 回调函数
      - (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
          fromAddress:(NSData *)address
    withFilterContext:(id)filterContext
    {
        NSLog(@"ReceiveData = %@, fromAddress = %@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding],[[NSString alloc] initWithData:address encoding:NSUTF8StringEncoding]);
        NSString *host = nil;
        uint16_t port = 0;
        [GCDAsyncUdpSocket getHost:&host port:&port fromAddress:address];//从此可以获取服务端回应的ip和端口 用于后面的tcp连接
       
        NSLog(@"Adress = %@ %i",host,port);
       
        //开启tcp连接
        sockeTCP = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
        //socket.delegate = self;
        NSError *err = nil;
        if(![sockeTCP connectToHost:host onPort:port error:&err])
        {
           
        }else
        {
            NSLog(@"tcp ok");
            [sockeTCP writeData:[@"发送tcp消息" dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
            [sockeTCP readDataWithTimeout:-1 tag:0];
        }
    }

    TCP 回调函数
       -(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
    {
        NSLog(@"%@",[NSString stringWithFormat:@"tcp连接到:%@",host]);
        [sockeTCP readDataWithTimeout:-1 tag:0];
       
    }

    -(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
    {
        NSString *newMessage = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"tcp newMessage = %@",newMessage);
    }
  • 相关阅读:
    关于vs2005、vs2008和vs2010项目互转的总结
    程序员
    八款JS框架介绍及比较
    ExtJS,JQuery,Dojo的小比较
    SQL触发器实例讲解
    五个最佳编程文本编辑器
    JAVA程序设计2——面向对象程序设计(上)
    JAVA程序设计3——包装类、常量池技术与单例类的实现
    JAVA程序设计1——开发环境搭建、数据类型及流程控制语句
    Web前端浏览器兼容初探【转】
  • 原文地址:https://www.cnblogs.com/cnsec/p/11515817.html
Copyright © 2011-2022 走看看