OStack程序员社区-中国程序员成长平台

标题: ios - 如何使用 GCD 使用 CFStreams [打印本页]

作者: 菜鸟教程小白    时间: 2022-12-13 03:02
标题: ios - 如何使用 GCD 使用 CFStreams

我是ios新手..

我想使用 Socket Connection 连接到服务器,我按照给出的教程进行操作 here

这工作正常,但我在主 UI 线程中做所有事情,但 View 被卡住,直到我从服务器得到响应......所以我用谷歌搜索了一下,在 ios 中找到了 GCD 的概念。 . 所以在我的按钮点击我调用下面的代码...

    [SVProgressHUD showWithStatus"rocessing.."];
    [self.view setUserInteractionEnabled:NO];


  qt = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(qt, ^{
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)ip, 54000, &readStream, &writeStream);

inputStream = (NSInputStream *)readStream;
outputStream = (NSOutputStream *)writeStream;
[inputStream setDelegate:self];
[outputStream setDelegate:self];

[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

[inputStream open];
[outputStream open];

NSData *data = [[NSData alloc] initWithData:[pinno dataUsingEncoding:NSASCIIStringEncoding]];
[outputStream write:[data bytes] maxLength:[data length]];
[outputStream close];
    });

我正在使用函数处理事件

- (void)streamNSStream *)theStream handleEventNSStreamEvent)streamEvent {

    NSLog(@"StreamEvent %i",streamEvent);
    switch (streamEvent) {

                            dispatch_async(dispatch_get_main_queue(), ^{[SVProgressHUD dismiss];
            });

        case NSStreamEventOpenCompleted:
            NSLog(@"Stream opened");
            break;

        case NSStreamEventHasBytesAvailable:
                 NSLog(@"Stream has byte Avaliable");

            if (theStream==inputStream) {

                while ([inputStream hasBytesAvailable]) {
                    uint8_t buffer[1024];
                    int len;
                    len = [inputStream read:buffer maxLength:sizeof(buffer)];
                    if(len>0){
                        NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
                        [self.view setUserInteractionEnabled:YES];

                        NSLog(@"output %@",output);


                    }
                }
            }
            break;

        case NSStreamEventErrorOccurred:
            [self.view setUserInteractionEnabled:YES];

            NSLog(@"Can not connect to the host!");
            break;

        case NSStreamEventEndEncountered:
            [self.view setUserInteractionEnabled:YES];

            break;

        default:
            [self.view setUserInteractionEnabled:YES];

            NSLog(@"Unknown event");

    }
}

使用上面的代码,我收到了一个对服务器的请求,服务器也发送了一个成功的响应,但是我在句柄事件方法中没有收到任何数据,但是我没有收到 hasbytesavaliable 事件.. 我的控制台日志是

2013-07-02 14:06:15.312 Multi[899:1c03] StreamEvent 1
2013-07-02 14:06:15.313 Multi[899:1c03] Stream opened
2013-07-02 14:06:15.313 Multi[899:1c03] StreamEvent 4
2013-07-02 14:06:15.313 Multi[899:1c03] Unknown event

知道我做错了什么......

Edit:Updated Code

点击按钮我启动计时器并调用连接方法..

counter=[NSTimer scheduledTimerWithTimeInterval:30.0 target:self selectorselector(stream:handleEvent userInfo:nil repeats:NO];


        qt = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_async(qt, ^{[self connect];});

连接方式:

  CFReadStreamRef readStream;
    CFWriteStreamRef writeStream;
    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)ip, 54000, &readStream, &writeStream);


    inputStream = (NSInputStream *)readStream;
    outputStream = (NSOutputStream *)writeStream;

    NSRunLoop *loop = [NSRunLoop currentRunLoop];

    [inputStream setDelegate:self];
    [outputStream setDelegate:self];

    [inputStream scheduleInRunLoop:loop forMode:NSDefaultRunLoopMode];
    [outputStream scheduleInRunLoop:loop forMode:NSDefaultRunLoopMode];

    [inputStream open];
    [outputStream open];

    NSData *data = [[NSData alloc] initWithData:[pinno dataUsingEncoding:NSASCIIStringEncoding]];
    [outputStream write:[data bytes] maxLength:[data length]];
    [outputStream close];

    [loop run];

流句柄事件

- (void)streamNSStream *)theStream handleEventNSStreamEvent)streamEvent {
    Username.text = @"";
    Password.text = @"";
    [self disconnect];
    if (counter!=nil){
        [counter invalidate];
        counter=nil;
    }

    NSLog(@"StreamEvent %i",streamEvent);
    switch (streamEvent) {

        case NSStreamEventOpenCompleted:
            NSLog(@"Stream opened");
            break;

        case NSStreamEventHasBytesAvailable:
            if (theStream==inputStream) {

                while ([inputStream hasBytesAvailable]) {
                    uint8_t buffer[1024];
                    int len;
                    len = [inputStream read:buffer maxLength:sizeof(buffer)];
                    if(len>0){
                        NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];

                        NSLog(@"output %@",output);
                        [SVProgressHUD dismiss];
                        main = [[Mainmenu alloc]
                                initWithNibName"Mainmenu"
                                bundle:nil];
                        //                        [self.view addSubview:main.view];
                        [self presentViewController:main animated:NO completion:NO];
                    }
                }
            }
            dispatch_async(dispatch_get_main_queue(), ^{[SVProgressHUD dismiss];
            });

            break;

        case NSStreamEventErrorOccurred:

            NSLog(@"Can not connect to the host!");
            dispatch_async(dispatch_get_main_queue(), ^{[self dismiss"Cannot connect to host!"];
            });

            break;

        case NSStreamEventEndEncountered:
            dispatch_async(dispatch_get_main_queue(), ^{[self dismiss"Connection Error"];
            });

            break;

        default:
            NSLog(@"Unknown event");
            dispatch_async(dispatch_get_main_queue(), ^{[self dismiss"Timeout Expired"];
            });

    }
}

还有断开连接的方法..

-(void) disconnect
{
    [inputStream close];
    [inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream close];
    [outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [inputStream setDelegate:nil];
    inputStream = nil;
    [outputStream setDelegate:nil];
    outputStream = nil;

}



Best Answer-推荐答案


如果您在单独的线程上运行它,那么您必须注意运行循环。你必须调用

[[NSRunLoop currentRunLoop] run];

在正确的时间。

如下更改您的这部分代码,它肯定会工作:

inputStream = (NSInputStream *)readStream;
outputStream = (NSOutputStream *)writeStream;

NSRunLoop *loop = [NSRunLoop currentRunLoop];

[inputStream setDelegate:self];
[outputStream setDelegate:self];

[inputStream scheduleInRunLoop:loop forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:loop forMode:NSDefaultRunLoopMode];

[inputStream open];
[outputStream open];

[loop run];

关于ios - 如何使用 GCD 使用 CFStreams,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17421497/






欢迎光临 OStack程序员社区-中国程序员成长平台 (https://ostack.cn/) Powered by Discuz! X3.4