簡體   English   中英

NSOutputStream不調用委托的NSStreamEventHasSpaceAvailable

[英]NSOutputStream not calling delegate's NSStreamEventHasSpaceAvailable

我已經通過使用輸入和輸出流實現了套接字。 外部體系結構負責一次發送一個請求進行寫入。

但是,如果任何請求均未返回No HasBytesAvailable ,則需要從隊列中刪除該請求,並告知請求超時。

對於所有其他請求,我能夠正確發送/接收數據,但是如果請求中的任何一個超時,那么之后HasSpaceAvailable不會再調用HasSpaceAvailable

我的代碼如下:

@實現CCCommandSocket

@synthesize connectionTimeoutTimer; @synthesize requestTimeoutTimer;

/ * * init * * @params * ipAddress:攝像機套接字的IP地址* portNumber:攝像機套接字的端口地址* * @return * Socket類型的對象,它將向ipAddress,portNumber發送連接請求* * /-(id)初始化{self = [super init]; 如果(自己){ip = @“ 192.168.42.1”; 端口= 7878;

    [self performSelectorOnMainThread:@selector(connectToCamera) withObject:nil waitUntilDone:YES];

    bytesReceivedCondition = [[NSCondition alloc] init];
    requestCompletedCondition = [[NSCondition alloc] init];
    requestReadyToProcess = [[NSCondition alloc] init];
    isBytesReceived = false;
    isRequestCompleted = false;
    isRequestReadyToProcess = false;
    responseString = [[NSString alloc] init];
    openBracesCount = 0;

    mutex = [[NSLock alloc] init];
}
return self;

}

實用標記

實用程序建立套接字通信。

/ * * connectToCamera * * /-(無效)connectToCamera {NSString * urlStr = ip;

if (![urlStr isEqualToString:@""])
{

    NSURL *website = [NSURL URLWithString:urlStr];

    if (!website)
    {
        NSString* messageString = [NSString stringWithFormat:@"%@ is not a valid URL",website];
        CCLog(LOG_ERROR, messageString);
        return;
    }

    CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)(urlStr), port, &readStream, &writeStream);

    //cast the CFStreams to NSStreams
    inputStream = (__bridge_transfer NSInputStream *)readStream;
    outputStream = (__bridge_transfer NSOutputStream *)writeStream;

    //set the delegate
    [inputStream setDelegate:self];
    [outputStream setDelegate:self];

    //schedule the stream on a run loop
    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

    //open the stream
    [inputStream open];
    [outputStream open];

    if(readStream==NULL)
    {
        CCLog(LOG_INFO, @"readstream NULL");
    }

    if(writeStream == NULL)
    {
        CCLog(LOG_INFO, @"writeStream NULL");
    }

    [self startConnectionTimeoutTimer];
}

}

實用標記-

實用方法

/ * * getIP * * @return *套接字連接到的IP地址* /-(NSString *)getIP {return ip; }

/ * * getPort * * @return *連接套接字的端口號* /-(int)getPort {return port; }

實用標記

pragma處理套接字回調。

  • (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {

    NSMutableArray * array = [[NSMutableArray alloc] init]; [array addObject:stream]; [array addObject:[NSNumber numberWithInt:eventCode]];

    [具有對象:數組的自我performSelectorInBackground:@selector(myStream :)]; }

  • (void)myStream:(NSMutableArray *)array {NSNumber * number = [array objectAtIndex:1]; int eventCode = [number intValue];

    switch(eventCode){case NSStreamEventErrorOccurred:{CCLog(LOG_ERROR,@“在命令套接字中NSStreamEventErrorOccurred”); // [自我斷開]; // [[[ErrorDetails getInstance] reportError:NSStreamEventErrorOccurred]; 打破; }

      //Read from stream case NSStreamEventHasBytesAvailable: { CCLog(LOG_INFO, @"In Command Socket NSStreamEventHasBytesAvailable"); [self handleCommandPortDataReceived]; break; } //Write to stream case NSStreamEventHasSpaceAvailable: { @synchronized(self) { [requestReadyToProcess lock]; while (isRequestReadyToProcess == false) { [requestReadyToProcess wait]; } [requestReadyToProcess unlock]; CCLog(LOG_INFO,@"In Command Socket NSStreamEventHasSpaceAvailable"); @try { @synchronized(requestString) { if(requestString != nil) { if(outputStream != nil) { int dataSent; uint8_t* data = (uint8_t *)[requestString cStringUsingEncoding:NSUTF8StringEncoding]; responseString = @""; //[requestReadyToProcess lock]; isRequestReadyToProcess = false; //[requestReadyToProcess signal]; dataSent = [outputStream write:data maxLength:strlen((char*)data)]; if(dataSent != -1) { NSString* message = [NSString stringWithFormat:@"Bytes written %d for request\\n %@",dataSent, requestString]; CCLog(LOG_REQUEST, message); requestString = nil; isBytesReceived = false; [bytesReceivedCondition lock]; while (isBytesReceived ==false) { [bytesReceivedCondition wait]; } [requestCompletedCondition lock]; isRequestCompleted = true; [requestCompletedCondition signal]; [requestCompletedCondition unlock]; [bytesReceivedCondition unlock]; } else { CCLog(LOG_INFO, @"Command Socket : Request not sent (dataSent == -1)"); responseString = @"{ \\"rval\\": -104}"; CCLog(LOG_RESPONSE, responseString); [self removeRequestFromQueue]; } } else { CCLog(LOG_INFO, @"in else :(outputStream != nil)"); } } } } @catch (NSException *e) { CCLog(LOG_WARNING, e.description); } } break; } case NSStreamEventNone: { CCLog(LOG_INFO, @"In Command Socket NSStreamEventNone"); break; } case NSStreamEventOpenCompleted: { CCLog(LOG_INFO, @"In Command Socket NSStreamEventOpenCompleted"); [self stopConnectionTimeoutTimer]; break; } case NSStreamEventEndEncountered: { CCLog(LOG_INFO, @"Command Socket NSStreamEventEndEncountered"); [self disconnectWithNotification:YES]; break; } 

    }}

/ * * execute * * @param * request:通過套接字發送到攝像機的命令* * @return * response:從攝像機接收的響應* * /-(NSString *)executeRequest:(NSString *)request {CCLog(LOG_INFO, @“命令套接字執行請求”);

[self performSelectorOnMainThread:@selector(startRequestTimeoutTimer) withObject:nil waitUntilDone:NO];

isRequestCompleted = false;
requestString = request;
responseString = @"";

[requestReadyToProcess lock];
isRequestReadyToProcess = true;
[requestReadyToProcess signal];
[requestReadyToProcess unlock];

[requestCompletedCondition lock];
while (isRequestCompleted ==false)
{
    [requestCompletedCondition wait];
}

CCLog(LOG_INFO, @"Command Socket Execute request : request completed");
[requestCompletedCondition unlock];
CCLog(LOG_RESPONSE, responseString);
return responseString;

}

實用標記

pragma處理連接超時

//發起連接時調用它-(void)startConnectionTimeoutTimer {[self stopConnectionTimeoutTimer]; //或確保在調用此方法之前已停止任何現有計時器

NSTimeInterval interval = 10.0; // Measured in seconds, is a double

self.connectionTimeoutTimer = [NSTimer scheduledTimerWithTimeInterval:interval
                                                               target:self
                                                             selector:@selector(handleConnectionTimeout)
                                                             userInfo:nil
                                                              repeats:NO];

}

  • (void)handleConnectionTimeout {responseString = @“ {\\” rval \\“:-103}”; CCLog(LOG_RESPONSE,responseString);

    [self removeRequestFromQueue];

    [自我disconnectWithNotification:是]; [self stopConnectionTimeoutTimer]; }

//發起連接時調用-(void)startRequestTimeoutTimer {[self stopRequestTimeoutTimer]; //或確保在調用此方法之前已停止任何現有計時器

NSTimeInterval interval = 20.0; // Measured in seconds, is a double

self.requestTimeoutTimer = [NSTimer scheduledTimerWithTimeInterval:interval
                                                               target:self
                                                             selector:@selector(handleRequestTimeout)
                                                             userInfo:nil
                                                              repeats:NO];

}

  • (void)handleRequestTimeout {responseString = @“ {\\” rval \\“:-103}”; CCLog(LOG_RESPONSE,responseString);

    [self connectToCamera]; [self stopRequestTimeoutTimer]; [self removeRequestFromQueue]; }

//成功連接后調用--(void)stopRequestTimeoutTimer {if(requestTimeoutTimer){[requestTimeoutTimer invalidate]; requestTimeoutTimer = nil; }}

-(無效)disconnectWithNotification:(BOOL)showNotification {CCLog(LOG_INFO,@“ Socket Disconnected”); [inputStream關閉]; [inputStream setDelegate:nil]; [inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; inputStream = nil;

[outputStream close];
[outputStream setDelegate:nil];
[outputStream removeFromRunLoop:[NSRunLoop currentRunLoop]
                        forMode:NSDefaultRunLoopMode];
outputStream = nil;
[[CCCore getInstance] disconnectWithNotification:showNotification];

}

//成功連接后調用此命令-(void)stopConnectionTimeoutTimer {if(connectionTimeoutTimer){[connectionTimeoutTimer invalidate ;; connectionTimeoutTimer = nil; }如果(requestTimeoutTimer){[requestTimeoutTimer無效]; requestTimeoutTimer = nil; }}

-(無效)handleCommandPortDataReceived {[互斥鎖]; [self stopRequestTimeoutTimer]; @try {long size = 1024; uint8_t buf [size]; unsigned int len = 0;

    do
    {
        // read input stream into buffer
        strcpy((char *)buf, "\0");
        len = [inputStream read:buf maxLength:size];

        //NSLog(@"Size = %ld Len = %d, Buf = %s",size, len, (char *)buf);

        // Following code checks if we have received complete response by matching "{" and "}"
        // from input stream. We continue to form response string unless braces are matched.
        if (len > 0)
        {
            // Create nsdata from buffer
            NSMutableData *_data = [[NSMutableData alloc] init];
            [_data appendBytes:(const void *)buf length:len];

            // create temporary string form nsdata
            NSString* currentString = [[NSString alloc] initWithData:_data encoding:NSUTF8StringEncoding];

            // check the occurances of { and } in current string
            int currentOpeningBraceCount = [[currentString componentsSeparatedByString:@"{"] count] - 1;
            int currentClosingBraceCount = [[currentString componentsSeparatedByString:@"}"] count] - 1;

            openBracesCount = (openBracesCount + currentOpeningBraceCount) - currentClosingBraceCount;
            responseString = [responseString stringByAppendingString:currentString];

            //                        NSLog(@"Total:%d currentOpen:%d currentClose:%d\n\n",openBracesCount, currentOpeningBraceCount, currentClosingBraceCount);
            //                        NSLog(@"Current String : %@\n\n",currentString);
            //                        NSLog(@"Final String : %@",finalString);
            //                        NSLog(@"+++++++++++++++++++++++++++++");
        }
        else
            break;

    } while (openBracesCount != 0);


    NSRange range = [responseString rangeOfString:@"get_file_complete"];
    if(range.location == NSNotFound)
    {
        //remove it from queue
        [bytesReceivedCondition lock];
        isBytesReceived = true;
        [bytesReceivedCondition signal];
        [bytesReceivedCondition unlock];
    }
    //responseString = @"";

}
@catch (NSException* e)
{
    [self connectToCamera];
}
[mutex unlock];

}

-(void)removeRequestFromQueue {//從隊列中將其刪除requestString = nil;

[requestReadyToProcess lock];
isRequestReadyToProcess = false;
[requestReadyToProcess unlock];

[requestCompletedCondition lock];
isRequestCompleted = true;
[requestCompletedCondition signal];
[requestCompletedCondition unlock];

}

@結束

您正在嘗試哪個操作系統版本? 我遇到了類似的問題,在10.7及更高版本中都很好,但是在10.6及以下版本中,我遇到了同樣的問題,您在進行一些調試,但到目前為止還沒有一個好的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM