CFNetwork解惑系列(一)是否要在kCFStreamEventHasBytesAvailable时读取所有数据

本次话题来自apple邮件列表《Must you read all you can on kCFStreamEventHasBytesAvailable?

CFSocket和CFStream作为CFNetwork的底层支持,也是我们讨论的范围。


      我们知道非block的CFStream一般有两种实现方式,一种是runloop,另一种是polling。在前者中,依靠注册的事件发生时,由runloop调度callback执行相应的工作。对于kCFStreamEventHasBytesAvailable事件,目前有两种实现,一种是尽力读取所有available数据,一种是每次设定一个一定长度的buffer,然后向其中写入数据,再取出来做后续处理,而不管此次available数据是否读完。没有读取完的可能因为buffer太小,只有部分数据被处理。别的可能原因,暂时想不到。即使在苹果的示例代码里,对于这两种实现也有分歧。在《CFNetwork Programming Guide》中采用后者;而CFFTPSample采用前者。根据邮件的回复,鼓励使用后者,说前者会引入一些问题。如果你在callback中运行runloop或者stream在多个runloop中被调度,就会在stream发出有available数据信号和第二次调用CFReadStreamRead()之间产生竞争,可能导致callback声称有available数据,而实际却没有的情况。最佳实践是在每次callback中只使用一次CFReadStreamRead(),并尽可能榨干所有available数据,这就要求一个大小适当的buffer。这个尺寸因应用而异。一般,对于繁忙的TCP Socket,以socket的内核buffer的大小(32K)为宜。


为方便理解,下面是引用的原文:

You are correct; it is not necessary to read all available bytes. Aslong as you read at least one byte, you will get anotherHasBytesAvailable callback if there are still bytes remaining. Infact, calling more than once can potentially introduce problems. Inparticular, if you run the run loop from within your callback, or thestream is scheduled on multiple run loops, you will have introduced arace between when the stream signals any remaining (or newly arrived)bytes and when you call CFReadStreamRead() for the second time. Theresult is you may get a callback claiming bytes are available when infact there are none.

Best practices and best performance is to call CFReadStreamRead() onlyonce per kCFStreamEventHasBytesAvailable callback, and provide abuffer large enough to be likely to drain all available bytes. Thatsize varies widely from application to application; you'll have toexperiment to find the best value for you. However, for busy TCPsockets, the size of the socket's kernel buffer (32k by default) is agood choice.

Hope that helps,
REW

On Apr 13, 2006, at 6:26 PM, James W. Walker wrote:

If you're using a CFReadStream in the non-blocking mode, and yourcallback receives kCFStreamEventHasBytesAvailable, what happens ifyou don't consume all the bytes that are available? In the best ofall possible worlds, you'd get anotherkCFStreamEventHasBytesAvailable message. The sample code in theCFNetwork Programming Guide seems to suggest that is so, because itjust reads what fits in one buffer onkCFStreamEventHasBytesAvailable. In contrast, CFFTPSample takespains to keep reading until either CFReadStreamHasBytesAvailablereturns false or CFReadStreamRead reads 0 bytes.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值