我有一个基本问题,
在使用 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
现在,当应用程序有东西要通过套接字(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 ;
}
}
我期望每当 OutputStream
发送数据时应用程序将继续接收事件,但我只收到一次......:(
请帮忙...
最佳答案
如果不等待该事件,写入调用将阻塞,直到有可用空间为止。一般来说,您希望将代码设计为异步工作,因此等待 NSStreamEventHasSpaceAvailable 是最好的解决方案。
至于您何时收到可用空间通知,see the documentation here :
If the delegate receives an NSStreamEventHasSpaceAvailable event and does not write anything to the stream, it does not receive further space-available events from the run loop until the NSOutputStream object receives more bytes. When this happens, the run loop is restarted for space-available events. If this scenario is likely in your implementation, you can have the delegate set a flag when it doesn’t write to the stream upon receiving an NSStreamEventHasSpaceAvailable event. Later, when your program has more bytes to write, it can check this flag and, if set, write to the output-stream instance directly.
There is no firm guideline on how many bytes to write at one time. Although it may be possible to write all the data to the stream in one event, this depends on external factors, such as the behavior of the kernel and device and socket characteristics. The best approach is to use some reasonable buffer size, such as 512 bytes, one kilobyte (as in the example above), or a page size (four kilobytes).
因此,只要您为每个事件写入数据,您就应该定期获取 NSStreamEventHasSpaceAvailable 事件。
关于cocoa - 写入问题 `NSOutputStream` 。,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7038380/