Iphone 从CFStreamCreatePairWithSocketToHost获取数据时出现的问题

Iphone 从CFStreamCreatePairWithSocketToHost获取数据时出现的问题,iphone,objective-c,sockets,nsstream,Iphone,Objective C,Sockets,Nsstream,我正在构建一个iPhone应用程序,它带有一个PC应用程序的插座,我需要从这个PC应用程序中获取图像。 这是我第一次使用“CFStreamCreatePairWithSocketToHost”。在我使用“NSOperation”建立套接字后,我调用 CFStreamClientContext streamContext={0,self,NULL,NULL}; BOOL success=CFReadStreamSetClient(myReadStream、kMyNetworkEvents、MyS

我正在构建一个iPhone应用程序,它带有一个PC应用程序的插座,我需要从这个PC应用程序中获取图像。 这是我第一次使用“CFStreamCreatePairWithSocketToHost”。在我使用“NSOperation”建立套接字后,我调用

CFStreamClientContext streamContext={0,self,NULL,NULL};
BOOL success=CFReadStreamSetClient(myReadStream、kMyNetworkEvents、MyStreamCallBack和streamContext);
CFReadStreamScheduleWithRunLoop(myReadStream,CFRunLoopGetCurrent(),kCFRunLoopDefaultMode);
然后我打电话

CFWriteStreamWrite(myWriteStream和writeBuffer,3);
//打开读取流。
如果(!CFReadStreamOpen(myReadStream)){
//通知错误
}
.
.
.
而(!取消&&!完成){
SInt32结果=CFRunLoopRunInMode(kCFRunLoopDefaultMode,0.25,否)

如果(结果==KCFRunlopUnstopped | |结果==KCFRunlopUnfinished){ 打破 }

如果([NSDate timeIntervalSinceReferenceDate]-\u lastRead)>MyConnectionTimeout){ //呼叫超时 取消=是

中断; }

//还可以处理流状态 CFStreamStatus status=CFReadStreamGetStatus(myReadStream); }
然后当我得到“kCFStreamEventHasBytesAvailable” 我用

while(CFReadStreamHasBytesAvailable(myReadStream))
{
CFReadStreamRead(myReadStream,readBuffer,1000);
//并缓冲这些字节
}
这是不可预测的,有时我了解整个情况,有时我只了解其中的一部分,我不明白是什么让情况有所不同。 有人知道这里出了什么问题吗?
谢谢

当您获得可用的kCFStreamEventHasBytesAvailable时,可能只有部分字节可用,而剩余的字节直到稍后才会到达

假设您期望总共有5000字节

由于网络定时不可预测,这是一种情况:

  • 两个数据包,每个包含1000字节,几乎立即到达
  • 您的回调将通过
    kCFStreamEventHasBytesAvailable
    调用,因为有2000个字节在等待
  • 您将在
    中执行代码循环,而
    循环两次,每次消耗1000字节
  • while
    循环退出,因为
    CFReadStream
    没有更多可用字节即使当前没有更多的字节等待,您的代码是否识别出您尚未拥有所有数据?
  • 另一个包含1000字节的数据包到达
  • 由于还有1000个字节等待,因此将使用
    kCFStreamEventHasBytesAvailable
    再次调用回调您准备好第二次回拨了吗?
  • 第5步和第6步再重复两次
  • 
    CFStreamClientContext streamContext = {0, self, NULL, NULL, NULL};
    BOOL success = CFReadStreamSetClient(myReadStream, kMyNetworkEvents,MyStreamCallBack,&streamContext);
    CFReadStreamScheduleWithRunLoop(myReadStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    
    
    CFWriteStreamWrite(myWriteStream, &writeBuffer, 3);
    // Open read stream.
     if (!CFReadStreamOpen(myReadStream)) {
      // Notify error
     }
    .
    .
    .
    while(!cancelled && !finished) {
      SInt32 result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.25, NO);

    if (result == kCFRunLoopRunStopped || result == kCFRunLoopRunFinished) { break; }

    if (([NSDate timeIntervalSinceReferenceDate] - _lastRead) > MyConnectionTimeout) { // Call timed out cancelled = YES;

    break; }

    // Also handle stream status CFStreamStatus status = CFReadStreamGetStatus(myReadStream); }
    
    while (CFReadStreamHasBytesAvailable(myReadStream))
    {
       CFReadStreamRead(myReadStream, readBuffer, 1000);
    //and buffer the the bytes
    }