Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/118.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios NSOutputstream被阻塞,尽管流是开放的_Ios_Objective C_Tcp_Nsoutputstream - Fatal编程技术网

Ios NSOutputstream被阻塞,尽管流是开放的

Ios NSOutputstream被阻塞,尽管流是开放的,ios,objective-c,tcp,nsoutputstream,Ios,Objective C,Tcp,Nsoutputstream,我试图在Objective/iOS上实现一个简单的TCP服务器。最简单的例子可以归结为以下几点:服务器应该维护多个TCP连接。每当读取数据(4字节)时,服务器应在该连接上回复一个答案(4字节) 我首先创建套接字侦听器,并将其安排在CFRunLoop中: CFSocketRef initialCfSock = CFSocketCreate(

我试图在Objective/iOS上实现一个简单的TCP服务器。最简单的例子可以归结为以下几点:服务器应该维护多个TCP连接。每当读取数据(4字节)时,服务器应在该连接上回复一个答案(4字节)

我首先创建套接字侦听器,并将其安排在CFRunLoop中:

CFSocketRef initialCfSock = CFSocketCreate(                                            
                                          kCFAllocatorDefault,
                                          PF_INET,
                                          SOCK_STREAM,
                                          IPPROTO_TCP,
                                          kCFSocketAcceptCallBack,
                                          &handleConnect,
                                          NULL);
if( ! initialCfSock ) return;
int yes=1;
setsockopt(CFSocketGetNative(initialCfSock), SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes));

struct sockaddr_in sin = {0};
sin.sin_len = sizeof(sin);
sin.sin_family = AF_INET;
sin.sin_port = htons(50000);
sin.sin_addr.s_addr= htonl(INADDR_ANY);
CFDataRef sincfd = CFDataCreate(
                                kCFAllocatorDefault,
                                (UInt8 *)&sin,
                                sizeof(sin));
if (kCFSocketSuccess != CFSocketSetAddress(initialCfSock, sincfd)) return;
CFRelease(sincfd);

CFRunLoopSourceRef socketsource = CFSocketCreateRunLoopSource(
                                                              kCFAllocatorDefault,
                                                              initialCfSock,
                                                              0);
CFRunLoopAddSource(
                   CFRunLoopGetCurrent(),
                   socketsource,
                   kCFRunLoopCommonModes);
CFRelease(socketsource);
CFRunLoopRun();
然后,在传入的连接上,调用连接处理程序(这是有效的):

最后,对于传入的字节,调用输入处理程序。读取四个字节并发送四个字节的回复:

void handleInput(CFReadStreamRef currentInputStream, CFStreamEventType event, void *clientCallbackInfo)
{
    NSLog(@"handleInput: inputStream=%p, outputStream=%p", inputStream, outputStream);

    switch(event) {
        case kCFStreamEventHasBytesAvailable:
        {
            // 1) begin
            unsigned int a;
            NSLog(@"before read: %d/%d, spaceAvail %d, bytesAvail %d", [inputStream streamStatus], [outputStream streamStatus], [outputStream hasSpaceAvailable], [inputStream hasBytesAvailable]);
            int err = [inputStream read:(uint8_t *)&a maxLength:sizeof(a)];
            NSLog(@"after read: %d/%d, spaceAvail %d, bytesAvail %d, err=%d", [inputStream streamStatus], [outputStream streamStatus], [outputStream hasSpaceAvailable], [inputStream hasBytesAvailable], err);

            NSLog(@"before write: %d/%d, spaceAvail %d, bytesAvail %d", [inputStream streamStatus], [outputStream streamStatus], [outputStream hasSpaceAvailable], [inputStream hasBytesAvailable]);
            err = [outputStream write:(uint8_t *) &a maxLength:sizeof(a)];
            NSLog(@"after write: %d/%d, spaceAvail %d, bytesAvail %d, err=%d", [inputStream streamStatus], [outputStream streamStatus], [outputStream hasSpaceAvailable], [inputStream hasBytesAvailable], err);
            // 1) end
            break;
        }
        case kCFStreamEventErrorOccurred:
        case kCFStreamEventEndEncountered:
        default:
            Log(@"[PK] handleInput: stream end/error");
            break;
    }

}
问题是:handleInput期间的[outputStream write:…]调用不发送字节,而是阻塞,什么也没有发生。客户端同时等待数据

这是日志:

handleConnect
handleConnect: inputStream=0x15576cb0, outputStream=0x15576ce0
before read: 2/2, spaceAvail 0, bytesAvail 1
after read: 2/2, spaceAvail 0, bytesAvail 1, err=4
before write: 2/2, spaceAvail 0, bytesAvail 0
但是:当我移动handleInput中标有1)到2)的行时,一切都正常。但我会同步地等待数据,这是我不想做的

然后,相应的日志文件如下所示:

handleConnect
handleConnect: inputStream=0x17632d30, outputStream=0x17632310
before read: 2/2, spaceAvail 0, bytesAvail 0
after read: 2/2, spaceAvail 1, bytesAvail 1, err=4
before write: 2/2, spaceAvail 1, bytesAvail 0
after write: 2/2, spaceAvail 1, bytesAvail 0, err=4
这里有什么问题

handleConnect
handleConnect: inputStream=0x17632d30, outputStream=0x17632310
before read: 2/2, spaceAvail 0, bytesAvail 0
after read: 2/2, spaceAvail 1, bytesAvail 1, err=4
before write: 2/2, spaceAvail 1, bytesAvail 0
after write: 2/2, spaceAvail 1, bytesAvail 0, err=4