J'ai une question fondamentale, En travaillant avec NSOutputStream
devons-nous attendre NSStreamEventHasSpaceAvailable
pour envoyer le paquet, donc nous pouvons appeler , [NSOutputStream write]
au fur et à mesure de ses besoins,
Je crois NSStream
devrait s'occuper de la fonction d'écriture...
Si ce n'est pas correct, veuillez donner votre avis sur la logique suivante,
\===== Pour écrire sur NSOutputStream
================= Avoir une file d'attente pour ajouter les paquets à envoyer. // 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
et sa mise en œuvre
#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
Maintenant, lorsque l'application a quelque chose à envoyer via socket( NSStream
), il doit l'ajouter à la file d'attente,
-(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;
}
et ce bout de code quand on obtient 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 ;
}
}
Je m'attendais à ce que l'application continue à recevoir l'événement, chaque fois que OutputStream
envoie des données, mais je ne les ai reçues qu'une seule fois... :( S'il vous plaît aider ...