如何让NSOutputStream立即发送或刷新数据包

时间:2011-06-29 22:09:00

标签: iphone bluetooth latency accessory nsoutputstream

使用外部附件框架连接到蓝牙配件时,我遇到延迟问题。发送数据时,我在控制台中获得以下自定义输出:

if( [stream hasSpaceAvailable] )
{
   NSLog( @"Space avail" );
}
else {
    NSLog(@"No space");
}
while( [stream hasSpaceAvailable] && ( [_outputBuffer length] > 0 ) )
{
    /* write as many bytes as possible */
    NSInteger written = [stream write:[_outputBuffer bytes] maxLength:[_outputBuffer length]];
    NSLog( @"wrote %i out of %i bytes to the stream", written, [_outputBuffer length] );
if( written == -1 )
    {
        /* error, bad */
        Log( @"Error writing bytes" );
        break;
    }
    else if( written > 0 )
    {
        /* remove the bytes from the buffer that were written */
        Log( @"erasing %i bytes", written );
        [_outputBuffer replaceBytesInRange:NSMakeRange( 0, written ) withBytes:nil length:0 ];
    }
}

这导致以下输出,其中立即包缓冲区是有效负载。

immediate pack buffer-> 040040008
Space avail
wrote 10 out of 10 bytes to the stream
immediate pack buffer-> 040010005
No space
immediate pack buffer-> 030040007
No space
wrote 20 out of 20 bytes to the stream
immediate pack buffer-> 030010004
No space
immediate pack buffer-> 040000004
Space avail
wrote 20 out of 20 bytes to the stream
immediate pack buffer-> 030000003
Space avail
wrote 10 out of 10 bytes to the stream
immediate pack buffer-> 040040008
Space avail
wrote 10 out of 10 bytes to the stream

注意它是如何连续写入“No Space”的,这意味着方法hasSpaceAvailable返回false并强制数据被缓冲,直到它返回true。

1)我需要知道的是为什么会发生这种情况?它是否在等待BT硬件的Ack?如果是这样,你如何删除这个阻止?

2)你如何做到这一点,它立即发送,我们基本上实时流数据而不缓冲?

3)是否有隐藏的API方法会禁用此阻止?

这是一个真正的问题,因为在向设备发送数据时不会有任何延迟/延迟,必须立即发送,以便硬件与iPhone命令同步。请帮忙。

3 个答案:

答案 0 :(得分:2)

对于大多数硬件(在开始下一个硬件之前完成发送当前数据包),你所要求的是不可能的,而通常的“流”范例(要求按顺序接收数据)是不可能的,所以带宽受限的)。

除非源和目的地重合,否则在物理上也不可能有零延迟。

实际问题似乎是基础流一次只排队一个数据包,即使该数据包只有10个字节长。我不知道为什么;可能是因为它是一个非常简单的协议。

处理这样一个队列的常用方法是注册适当的委托回调,并在流有空间时发送尽可能多的数据,而不是等到下次尝试发送数据时(出现做你正在做的事。)

答案 1 :(得分:0)

问题是HandleEvent委托函数是一个异步调用。所以每次它都没有命中委托。 你可以做的是,同时在一个数组中包含命令集合,打开会话,调用writeData函数。这里发生的是,一旦调用了写入数据,就不需要调用HandleEvent函数了每一个命令。 对于数组项的计数,writeData函数中的计数递增,直到count == arrayItems,Delegate未被命中..

所以列表中的所有命令都是逐个发送的。

答案 2 :(得分:-1)

我面临同样的问题但是在不同的情况下。

场景:首次连接时,iPhone应用可以与PED进行通信。但是当PED电池耗尽或关闭然后打开时,尽管有活动会话和有效输出流,app仍无法与PED通信。输出蒸汽表示它没有写任何东西。

解决方案:当PED切换时,应用会收到通知,此时我会让应用程序杀死EASession并在PED获得连接时再次创建它。不确定它是否是最佳解决方案。如果有的话,请提出另一种解决方案。