2

基本的な質問が1つあります。作業中に、パケットの送信NSOutputStreamを待つ必要があります。そうすれば、必要に応じて、必要に応じて電話をかけることができます。NSStreamEventHasSpaceAvailable[NSOutputStream write]

NSStreamは書き込み関数の世話をする必要があると信じています...

これが正しくない場合は、次のロジックについての見解を提供してください。

=====書き込むにはNSOutputStream=================送信するパケットを追加するためのキューがあります//StreamQueue.h

@interface StreamQueue : NSObject <NSCoding>
{
    NSMutableArray * data;
    NSRecursiveLock * theLock;
}

#pragma mark �Initialization & Deallocation�
- (id)init;
- (id)initWithQueue:(CommQueue *)queue;
- (id)initWithCoder:(NSCoder *)coder;
- (void)dealloc;
- (void)encodeWithCoder:(NSCoder *)coder;

#pragma mark
#pragma mark �Accessor Methods�
- (int)size;
- (BOOL)isEmpty;
- (id)top;
- (NSArray *)data;

#pragma mark
#pragma mark �Modifier Methods�
- (void)enqueue:(id)object;
- (id)dequeue;
- (void)removeAll;
@end

とその実装

#import "StreamQueue.h"


@implementation StreamQueue
#pragma mark �Initialization & Deallocation�
- (id)init
{
    if (self = [super init]) {
        data = [[NSMutableArray alloc] init];
        theLock = [[NSRecursiveLock alloc] init];
    }
    return self;
}

- (id)initWithQueue:(StreamQueue *)queue
{
    if (self = [super init]) {
        data = [[NSMutableArray alloc] initWithArray:[queue data]];
        theLock = [[NSRecursiveLock alloc] init];
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)coder
{
    if (self = [super init]) {
        data = [[NSMutableArray alloc] initWithArray:[coder decodeObject]];
        theLock = [[NSRecursiveLock alloc] init];
    }
    return self;
}

- (void)dealloc
{
    [data release];
    [theLock release];
    [super dealloc];
}

- (void)encodeWithCoder:(NSCoder *)coder;
{
    [coder encodeObject:data];
}

#pragma mark
#pragma mark �Accessor Methods�
- (int)size
{
    int size;
    [theLock lock];
    size = [data count];
    [theLock unlock];
    return size;
}

- (BOOL)isEmpty
{
    BOOL empty;
    [theLock lock];
    empty = ([data count] == 0);
    [theLock unlock];
    return empty;
}

- (id)top
{
    id object = nil;
    [theLock lock];
    if (![self isEmpty])
        object = [data objectAtIndex:0];
    [theLock unlock];
    return object;
}

- (NSArray *)data
{
    NSArray * array;
    [theLock lock];
    array = [NSArray arrayWithArray:data];
    [theLock unlock];
    return array;
}

#pragma mark
#pragma mark �Modifier Methods�
- (void)enqueue:(id)object
{
    [theLock lock];
    [data addObject:object];
    [theLock unlock];
}

- (id)dequeue
{
    id object = [self top];
    if (object != nil) {
        [theLock lock];
        [object retain];
        [data removeObjectAtIndex:0];
        [theLock unlock];
    }
    return [object autorelease];
}

- (void)removeAll
{
    [theLock lock];
    while (![self isEmpty])
        [data removeObjectAtIndex:0];
    [theLock unlock];
}
@end

これで、アプリケーションにsocket(NSStream)を介して送信するものがある場合、それをキューに追加する必要があります。

-(bool)sendRawData:(const uint8_t *)data length:(int)len{

    // if still negotiating then don't send data
    assert(!networkConnected);

    NSData *pData  = [NSData dataWithBytes:(const void *)data length:len];

    // pToSendPacket is of type StreamQueue 
    [pToSendPacket enqueue:pData];

    return;
}

そして、このコードはNSHasSpaceAvailableEvent

-(void)gotSpaceAvailable{
    // is there any pending packets that to be send. 
    NSData *pData = (NSData *)[pToSendPacket dequeue];

    if(pData == nil){
        // no pending packets.. 
        return;
    }

    const uint8_t *data = (const uint8_t *)[pData bytes];
    int len = [pData length];

    int sendlength = [pOutputStream write:data maxLength:len];

    if(sendlength == -1 ){
        NSError *theError = [pOutputStream streamError];
        NSString *pString = [theError localizedDescription];
        int errorCode = [theError code];
        return ;
    }
}

アプリケーションがデータを送信するたびにイベントを受信し続けることを期待していましたが、受信したのはOutputStream1回だけです...:(助けてください...

4

1 に答える 1

8

イベントを待機しない場合、書き込み呼び出しは、スペースが利用可能になるまでブロックされます。一般に、非同期で動作するようにコードを設計することを目的とするため、NSStreamEventHasSpaceAvailable を待つことが最善の解決策です。

空き容量の通知を受け取るタイミングについては、次のドキュメントを参照してください

デリゲートが NSStreamEventHasSpaceAvailable イベントを受け取り、ストリームに何も書き込まない場合、NSOutputStream オブジェクトがさらにバイトを受け取るまで、実行ループからそれ以上の空き容量イベントを受け取ることはありません。これが発生すると、スペースが利用可能なイベントのために実行ループが再開されます。実装でこのシナリオが発生する可能性が高い場合は、デリゲートが NSStreamEventHasSpaceAvailable イベントの受信時にストリームに書き込みを行わないときにフラグを設定することができます。後で、プログラムに書き込むバイトが増えると、このフラグをチェックし、設定されている場合は出力ストリーム インスタンスに直接書き込むことができます。

一度に書き込むバイト数に関する明確なガイドラインはありません。1 回のイベントですべてのデータをストリームに書き込むことができる場合もありますが、これは、カーネルやデバイスの動作、ソケットの特性など、外部要因に依存します。最適な方法は、512 バイト、1 キロバイト (上記の例のように)、またはページ サイズ (4 キロバイト) などの適切なバッファー サイズを使用することです。

したがって、各イベントのデータを書き込む限り、通常の NSStreamEventHasSpaceAvailable イベントを取得する必要があります。

于 2011-08-12T09:54:00.333 に答える