我想创建一个应由单个线程处理的tcp监听器类,即所有io操作都应由单个线程执行。
当消息到达inputStream时触发事件,多个线程可以向侦听器线程添加任务以写入输出流。
我从代码开始,但坚持理解runloop概念。
我的问题是我可以将一个任务添加到runloop,比如输入源(这里是socket)警告runloop吗?
如果我从runloop中删除inputresources,关联的线程是否会终止其执行?如果没有,我怎么能终止线程的执行。
我试过的代码
#import "TCPControler.h"
@implementation TCPListener
{
NSInputStream *in;
NSOutputStream *out;
NSString *ipAddress;
int portNum;
}
-(id) initWithAddress:(NSString *) ip portNumber: (int) port{
self=[super init];
if(self){
ipAddress=ip;
portNum=port;
}
return self;
}
-(void) start{
dispatch_queue_t q=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_async(q, ^{ [self runEventLoop];});
}
-(void) runEventLoop{
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"10.2.2.63", 2208, &readStream, &writeStream);
in = (__bridge NSInputStream *)(readStream);
out = (__bridge NSOutputStream *)writeStream;
[in setDelegate:self];
[out setDelegate:self];
[in scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[out scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[in open];
[out open];
[[NSRunLoop currentRunLoop]run];
}
-(void) stop{
NSLog(@"Closing streams.");
[in close];
[out close];
[in removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[out removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[in setDelegate:nil];
[out setDelegate:nil];
in = nil;
out = nil;
}
-(void) onRead{
}
-(void) onConnected{
}
-(void) onDisconnected{
}
-(void) write:(NSString *) data{
}
-(void) stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{
@try {
switch (eventCode) {
case NSStreamEventOpenCompleted:
NSLog(@"Event fired NSStreamEventOpenCompleted %d",aStream==in);
break;
case NSStreamEventHasBytesAvailable:
NSLog(@"Event fired NSStreamEventHasBytesAvailable %d",aStream==in);
if(aStream == in) {
NSLog(@"inputStream is ready.");
uint8_t buf[1024];
NSInteger len=0;
len = [in read:buf maxLength:1024];
if(len > 0) {
NSMutableData* data=[[NSMutableData alloc] initWithLength:0];
[data appendBytes: (const void *)buf length:len];
NSString *s = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(@" %@",s);
}
}
break;
case NSStreamEventNone:
NSLog(@"Event fired NSStreamEventNone %d",aStream==in);
break;
case NSStreamEventHasSpaceAvailable:
NSLog(@"Event fired NSStreamEventHasSpaceAvailable %d",aStream==in);
break;
case NSStreamEventErrorOccurred:
NSLog(@"Event fired NSStreamEventErrorOccurred %d",aStream==in);
break;
case NSStreamEventEndEncountered:
NSLog(@"Event fired NSStreamEventEndEncountered %d",aStream==in);
[self stop];
break;
default:
NSLog(@"Event fired ");
break;
}
}
@catch (NSException *exception) {
NSLog(@"Event fired %@",exception);
}
@finally {
}
}
@end
TCPControler *con=[[TCPControler alloc] initWithAddress:@"10.2.2.63" portNumber:80];
[con start];
请建议一个好的设计。提前谢谢。
答案 0 :(得分:0)
https://github.com/robbiehanson/CocoaAsyncSocket
使用GCDAsyncSocket,您可以指定要使用的线程。
您可以在自述文件和https://github.com/robbiehanson/CocoaAsyncSocket/wiki
中找到有关如何处理套接字的大量信息