【问题标题】:CFWriteStreamWrite stopped before finishingCFWriteStreamWrite 在完成前停止
【发布时间】:2011-12-11 08:51:11
【问题描述】:

我正在尝试使用 CFWriteStreamWrite 将数据从 iPhone 发送到运行 macox 的笔记本电脑。

在笔记本电脑(macOS)上,接收代码是

int sockfd, newsockfd, portno;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2) {
    fprintf(stderr,"ERROR, no port provided\n");
    exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
    error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
    error("ERROR on binding");
PacketSize = 672629;
char *blob = (char *)malloc(PacketSize*sizeof(char));
listen(sockfd,5);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) error("ERROR on accept");

uint64_t ByteToRead = PacketSize;
char *buffer= blob;

/*
n=recv(newsockfd, blob, PacketSize, MSG_WAITALL);
*/
while (ByteToRead>0)
{
    n = recv(newsockfd, buffer, ByteToRead, 0);
    //n = read(newsockfd,buffer,min(1024, ByteToRead));
    if (n < 0)
        error("ERROR reading from socket");
    ByteToRead -= n;
    buffer += n;
    printf ("just read %d, %d left\n", n, ByteToRead);
}

而在手机端(ios5),我使用的是runloop方法:

NSString *iHostname = [NSString stringWithFormat:@"192.168.1.66"];
NSString *iPort = [NSString stringWithFormat:@"2553"];

static const CFOptionFlags kWriteNetworkEvents = kCFStreamEventEndEncountered |
kCFStreamEventErrorOccurred |
kCFStreamEventCanAcceptBytes |
kCFStreamEventOpenCompleted |
kCFStreamEventNone;
CFStreamClientContext ctxt = {0,(void*)self,NULL,NULL,NULL};
CFHostRef hostRef = CFHostCreateWithName(kCFAllocatorDefault,(CFStringRef)iHostname);

CFStreamCreatePairWithSocketToCFHost(kCFAllocatorDefault, hostRef, [iPort intValue],
                                     NULL, &writeStream);

CFWriteStreamSetClient(writeStream, kWriteNetworkEvents, MyWriteStreamClientCallBack, &ctxt);

CFWriteStreamScheduleWithRunLoop(writeStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
CFWriteStreamOpen(writeStream);

回调函数是

static void MyWriteStreamClientCallBack( CFWriteStreamRef stream, CFStreamEventType type, void *clientCallBackInfo ) 
{
UploadTableViewController *self = [[(UploadTableViewController *)clientCallBackInfo retain] autorelease];

NSLog(@"in call back");
switch (type)
{
    case kCFStreamEventEndEncountered:
    {
        NSLog(@"in CallBack: kCFStreamEventEndEncounteredd");
        CFWriteStreamClose(stream);
        break;
    }
    case kCFStreamEventErrorOccurred:
    {
        NSLog(@"in CallBack: kCFStreamEventErrorOccurred");
        //CFStreamError error = CFWriteStreamGetError(stream);
        //NSLog([[self errorFromCFStreamError:error] domain]);
        //NSLog(@"%d",[[self errorFromCFStreamError:error] code] );
        break;

    }
    case kCFStreamEventCanAcceptBytes:
    {            
        NSLog(@"in CallBack: kCFStreamEventCanAcceptBytes, %llu bytes to send", self->ByteToSent);

        CFIndex ByteSent = CFWriteStreamWrite(stream,  self->WriteStart, (CFIndex)(self->ByteToSent));
        if (ByteSent > 0)
        {
            self->ByteToSent -= ByteSent;
            self->WriteStart += ByteSent;
            NSLog(@"just wrote %ld bytes, %lld left", ByteSent, self->ByteToSent);
        }
        else
            NSLog(@"CFWriteStreamWrite returned %ld", ByteSent);


    }
    case kCFStreamEventNone:
    {
        NSLog(@"in CallBack: kCFStreamEventNone");
        break;
    }
    case kCFStreamEventOpenCompleted:
    {
        NSLog(@"in CallBack: kCFStreamEventNone");
        break;
    }
}

问题是发送在中间停止。例如,在电话上我从 XCODE 得到这个:

2011-10-19 18:26:04.062 whereamI[1818:707] in CallBack: kCFStreamEventNone
2011-10-19 18:26:26.736 whereamI[1818:707] in call back
2011-10-19 18:26:26.738 whereamI[1818:707] in CallBack: kCFStreamEventNone
2011-10-19 18:26:26.739 whereamI[1818:707] in call back
2011-10-19 18:26:26.740 whereamI[1818:707] in CallBack: kCFStreamEventCanAcceptBytes,         672629 bytes to send
2011-10-19 18:26:26.745 whereamI[1818:707] just wrote 131768 bytes, 540861 left
2011-10-19 18:26:26.746 whereamI[1818:707] in CallBack: kCFStreamEventNone
2011-10-19 18:26:26.753 whereamI[1818:707] in call back
2011-10-19 18:26:26.755 whereamI[1818:707] in CallBack: kCFStreamEventCanAcceptBytes, 540861 bytes to send
2011-10-19 18:26:26.756 whereamI[1818:707] CFWriteStreamWrite returned -1
2011-10-19 18:26:26.757 whereamI[1818:707] in CallBack: kCFStreamEventNone
2011-10-19 18:26:26.758 whereamI[1818:707] in call back
2011-10-19 18:26:26.759 whereamI[1818:707] in CallBack: kCFStreamEventErrorOccurred
2011-10-19 18:45:49.101 whereamI[1818:707] in call back
2011-10-19 18:45:49.102 whereamI[1818:707] in CallBack: kCFStreamEventNone
2011-10-19 18:45:49.104 whereamI[1818:707] in call back
2011-10-19 18:45:49.105 whereamI[1818:707] in CallBack: kCFStreamEventCanAcceptBytes, 672629 bytes to send
2011-10-19 18:45:49.110 whereamI[1818:707] just wrote 131768 bytes, 540861 left
2011-10-19 18:45:49.111 whereamI[1818:707] in CallBack: kCFStreamEventNone
2011-10-19 18:45:49.120 whereamI[1818:707] in call back
2011-10-19 18:45:49.121 whereamI[1818:707] in CallBack: kCFStreamEventCanAcceptBytes, 540861 bytes to send
2011-10-19 18:45:49.123 whereamI[1818:707] just wrote 2896 bytes, 537965 left
2011-10-19 18:45:49.124 whereamI[1818:707] in CallBack: kCFStreamEventNone

列表其实很长,这只是结尾部分。

在笔记本电脑上,输出是

max@machine:~/socket$ ./newserver.x 2553
just read 1448, 671181 left
ERROR reading from socket: Socket operation on non-socket

在C代码中我也尝试过

n=recv(newsockfd, blob, PacketSize, MSG_WAITALL);

没有循环,并且

n = read(newsockfd,buffer,min(1024, ByteToRead));

在循环中。两者也无法完成传输。

在电话上我也尝试过只使用 BSD 套接字:

n = write(sockfd, &PackageSize, sizeof(PackageSize));

配对

n=recv(newsockfd, blob, PacketSize, MSG_WAITALL);

并且传输确实成功完成。

所以,请帮忙。

谢谢。

【问题讨论】:

  • 只有当要发送的数据包足够大时才会出现这个问题。对于较小的大小,例如 uint64_t 整数,传输成功。
  • 当您记录“CFWriteStreamWrite 返回 -1”时,请尝试同时记录 errno 和 strerror(errno)。

标签: iphone objective-c network-programming sockets


【解决方案1】:

这一行是错误的:

char *buffer= &blob;

应该这样说:

char *buffer = blob;

【讨论】:

  • 不错的收获!!固定的。现在转移还没有完成。在手机上,CFWriteStreamWrite 返回 -1,还剩 309181 个字节,笔记本电脑端的 recv 每次循环迭代读取 1448 个字节并最终挂在那里。
  • 让我困惑的是,如果 kCFStreamEventCanAcceptBytes==YES,会出现什么问题导致 CFWriteStreamWrite 返回 -1?我还尝试通过 CFWriteStreamWrite 在手机上限制写入的大小,并且得到了相同的结果。
  • CFWriteStreamWrite 会因某种超时而终止吗?
  • 啊哈,解决了。我实际上有两个这样的愚蠢错误。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-11
  • 1970-01-01
  • 2014-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多