由于iOS开发框架中的CFWrite/ReadStream,我在尝试建立双向异步通信时遇到了一个问题
我开始创建一个套接字连接,一切似乎都是正确的:
CFSocketContext socketCtx = {0, self, NULL, NULL, NULL};
socket = CFSocketCreate(NULL, PF_INET, SOCK_STREAM, IPPROTO_TCP,kCFSocketConnectCallBack, (CFSocketCallBack)onConnectOrDisconnect, &socketCtx);
CFSocketEnableCallBacks(socket, kCFSocketConnectCallBack);
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_len = sizeof(addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(appDelegate.portSocket);
addr.sin_addr.s_addr = inet_addr([adress cStringUsingEncoding:NSASCIIStringEncoding]);
CFDataRef connectAddr = CFDataCreate(NULL, (unsigned char *)&addr, sizeof(addr));
CFRunLoopSourceRef sourceRef = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), sourceRef, kCFRunLoopCommonModes);
CFRelease(sourceRef);
CFSocketConnectToAddress(socket, connectAddr, -1);
然后,在我的连接回调中,我创建了两个流,一个用于读取,另一个用于写入:
void onConnectOrDisconnect(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address,
const void *data, void *info)
{
TCPClient * clientTCP = (TCPClient *)info;
if(data==NULL)
{
[clientTCP ConnectionSuccess];
}else {
SInt32 *error = (SInt32*)data;
NSLog(@"Connection error : %d", *error);
StreamErrorOccured(clientTCP);
}
}
- (void) ConnectionSuccess
{
CFStreamCreatePairWithSocket(kCFAllocatorDefault, CFSocketGetNative(socket), &readStream, &writeStream);
CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
CFStreamClientContext dataStreamContext = {0, self, NULL, NULL, NULL};
CFOptionFlags events = kCFStreamEventHasBytesAvailable | kCFStreamEventOpenCompleted;
if (CFReadStreamSetClient(readStream, events, readStreamEventCallBack , &dataStreamContext))
{
CFReadStreamScheduleWithRunLoop(readStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
}
if (CFWriteStreamSetClient(writeStream, kCFStreamEventOpenCompleted | kCFStreamEventCanAcceptBytes | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered,
writeStreamEventCallBack, &dataStreamContext))
{
CFWriteStreamScheduleWithRunLoop(writeStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
}else {
NSLog(@"can't create write stream client");
}
CFReadStreamOpen(readStream);
CFWriteStreamOpen(writeStream);
NSLog(@"Connection Success");
}
请注意,我注册了kCFStreamEventCanAcceptBytes事件和kCFStream EventOpenCompleted事件的回调。在这个回调中,我可以看到kCFStreamEventOpenCompleted发生了,但kCFStream EventCanAcceptBytes从未发生
当我尝试在流上写时,我会检查流的可用性,这要归功于:CFWriteStreamCanAcceptBytes(writeStream)。此函数总是返回false
如果我尝试在不调用CFWriteStreamCanAcceptBytes的情况下对流进行写入,则写入操作将永远循环。我的问题是:1.为什么我没有收到任何kCFStreamEventCanAcceptBytes事件?2.为什么我不能在流媒体上写作?
我发现我的问题完全一样:类似的问题,但没有人回复他
也许我会更幸运!
干杯,
我不知道答案,但我也遇到了这个问题。解决方案是在您的writeStreamEventCallBack中接收事件"kCFStreamEventCanAcceptBytes",并在此回调函数上写入数据。事实上,问题是,如果您没有在"kCFStreamEventCanAcceptBytes"事件上发送任何数据,那么下次就无法发送数据。
一页苹果开发文档上写着:
当您使用CFStream API进行联网时,套接字上的读写操作可能会被阻止。防止阻塞:
-
调用CFReadStreamSetClient和CFWriteStreamSetClient进行注册以接收与流相关的事件通知。
-
调用CFReadStreamScheduleWithRunLoop和CFWriteStreamScheduleWithRun loop以在运行循环上调度流,以便接收与流相关的事件通知。
-
调用CFReadStreamOpen和CFWriteStreamOpen打开每个流。
-
收到kCFStreamEventHasBytesAvailable通知后只读。仅在收到kCFStreamEventCanAcceptBytes通知后写入。