Cocoa NSFileHandle函数AcceptConnectionInBackground和Notify在第二次调用时不工作

Cocoa NSFileHandle函数AcceptConnectionInBackground和Notify在第二次调用时不工作,cocoa,macos,sockets,Cocoa,Macos,Sockets,我正在使用cocoa,我正在尝试为我正在编写的程序创建一个tcp套接字服务器,我正在使用NSFileHandle和方法acceptConnectionInBackgroundAndNotify。我一直在跟踪来自的代码 我遇到的问题是,我可以连接我的客户端一次,但当我再次尝试连接时,我会收到一个连接拒绝错误 在我第一次连接之前,sudo lsof-I-p命令返回以下信息: RubyBeat 23964 pauljohnson 8u IPv4 0x0632c274 0t0

我正在使用cocoa,我正在尝试为我正在编写的程序创建一个tcp套接字服务器,我正在使用NSFileHandle和方法acceptConnectionInBackgroundAndNotify。我一直在跟踪来自的代码

我遇到的问题是,我可以连接我的客户端一次,但当我再次尝试连接时,我会收到一个连接拒绝错误

在我第一次连接之前,sudo lsof-I-p命令返回以下信息:

RubyBeat  23964    pauljohnson    8u  IPv4 0x0632c274      0t0    TCP *:1234 (LISTEN)
第一次与客户端连接后,我得到以下信息:

RubyBeat  23964    pauljohnson    5u  IPv4 0x06a30334      0t0    TCP localhost:1234->localhost:51579 (CLOSED)
我的应用程序似乎没有在第一次连接后重新打开套接字以侦听连接,并且在我尝试第二次连接时收到错误号22

我正在cocoa中使用垃圾收集,我想知道这是否会导致套接字出现问题

我的代码是:

    [self createSocket];
}

-(void)createSocket 
{
    // create socket and wait for events to come in
    NSSocketPort* serverSock = [[NSSocketPort alloc] initWithTCPPort: 1234];
    socketHandle = [[NSFileHandle alloc] initWithFileDescriptor: [serverSock socket]
                                                 closeOnDealloc: NO];

    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(newConnection:) 
                                                 name: NSFileHandleConnectionAcceptedNotification
                                               object: socketHandle];

    [socketHandle acceptConnectionInBackgroundAndNotify];
}

- (void)newConnection:(NSNotification*)notification
{
    NSLog(@"connection accepted");

    NSDictionary* userInfo = [notification userInfo];
    NSFileHandle* remoteFileHandle = [userInfo objectForKey:
                                      NSFileHandleNotificationFileHandleItem];

    if([[userInfo allKeys] containsObject:@"NSFileHandleError"]){
        NSNumber* errorNo = [userInfo objectForKey:@"NSFileHandleError"];
        if( errorNo ) {
            NSLog(@"NSFileHandle Error: %@", errorNo);
            return;
        }
    }

    [socketHandle acceptConnectionInBackgroundAndNotify];


    [[NSNotificationCenter defaultCenter] addObserver:self 
       selector: @selector(processSocketData:)
           name: NSFileHandleReadCompletionNotification
         object: remoteFileHandle];

    // Send a message to the client, acknowledging that the connection was accepted
    [remoteFileHandle writeData: [@"OK" dataUsingEncoding: NSASCIIStringEncoding]];

    [remoteFileHandle readInBackgroundAndNotify];
}

/*
 Handle client data
 */
- (void)processSocketData:(NSNotification *)note
{
    NSData *data = [[note userInfo]
                    objectForKey:NSFileHandleNotificationDataItem];

    NSNumber* errorNo = [[note userInfo] objectForKey:@"NSFileHandleError"];
    if( errorNo ) {
        NSLog(@"NSFileHandle Error: %@", errorNo);
        return;
    }

    // Do something here with your data

    // search string for \n\n that terminates event
    NSString* stringData = [[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding];
    NSLog(@"data received: %@", stringData);

    NSDictionary* lastEvent = nil;

    NSRange range =  [stringData rangeOfString: @"\n\n"];

    if (range.location != NSNotFound) {
        NSArray* subStrings = [stringData componentsSeparatedByString:@"\n\n"];

        NSMutableArray* events = [[NSMutableArray alloc] init]; 

        [eventBuffer appendString: [subStrings objectAtIndex: 0]];

        // handle first event - could be in parts
        NSDictionary * json = (NSDictionary*)[eventBuffer JSONValue];

        [events addObject:json];

        for(int i = 1; i < [subStrings count]-1; i++){
            NSString* subString = [subStrings indexOfObject:i];

            NSDictionary * eventJson = (NSDictionary*)[subString JSONValue];

            [events addObject:eventJson];
        }

        // we have at least one event to draw here

        for(NSDictionary* event in events){
            NSLog(@"event: %@", [event objectForKey:@"type"]);
        }

        lastEvent = [events lastObject];

        // clear eventBuffer
        [eventBuffer setString:@""];

        // add end of data to eventBuffer?
    }else {
        [eventBuffer appendString:stringData];

    }

    // check event if it is a program exit event then stop receiving data

    if([[lastEvent objectForKey: @"type"] compare: @"exit"] != NSOrderedSame){
        // Tell file handle to continue waiting for data
        [[note object] readInBackgroundAndNotify];
    }else {


        NSLog(@"exit received stopping receiving data");
    }

}
[self-createSocket];
}
-(void)createSocket
{
//创建套接字并等待事件进入
NSSocketPort*serverSock=[[NSSocketPort alloc]initWithTCPPort:1234];
socketHandle=[[NSFileHandle alloc]initWithFileDescriptor:[serverSock套接字]
CloseOnDeloc:否];
[[NSNotificationCenter defaultCenter]添加观察者:自选择器:@selector(新连接:)
名称:NSFileHandleConnectionAcceptedNotification
对象:socketHandle];
[socketHandle AcceptConnectionInBackground和Notify];
}
-(无效)新建连接:(NSNotification*)通知
{
NSLog(@“已接受连接”);
NSDictionary*userInfo=[notification userInfo];
NSFileHandle*remoteFileHandle=[userInfo objectForKey:
NSFileHandleNotification FileHandleItem];
如果([[userInfo allKeys]包含对象:@“NSFileHandleError”]){
NSNumber*errorNo=[userInfo objectForKey:@“NSFileHandleError”];
如果(错误号){
NSLog(@“NSFileHandle错误:%@”,错误号);
返回;
}
}
[socketHandle AcceptConnectionInBackground和Notify];
[[NSNotificationCenter defaultCenter]添加观察者:self
选择器:@selector(processSocketData:)
名称:NSFileHandlerReadCompletionNotification
对象:remoteFileHandle];
//向客户端发送消息,确认已接受连接
[remoteFileHandle writeData:[@“确定”数据使用编码:NSASCIIStringEncoding];
[remoteFileHandle readInBackgroundAndNotify];
}
/*
处理客户端数据
*/
-(无效)processSocketData:(NSNotification*)注释
{
NSData*data=[[注意用户信息]
objectForKey:NSFileHandleNotificationDataItem];
NSNumber*errorNo=[[note userInfo]objectForKey:@“NSFileHandleError”];
如果(错误号){
NSLog(@“NSFileHandle错误:%@”,错误号);
返回;
}
//在这里用你的数据做点什么
//搜索终止事件的字符串\n\n
NSString*stringData=[[NSString alloc]initWithData:数据编码:NSASCIIStringEncoding];
NSLog(@“接收数据:%@”,stringData);
NSDictionary*lastEvent=nil;
NSRange range=[stringData rangeOfString:@“\n\n”];
if(range.location!=NSNotFound){
NSArray*子字符串=[stringData组件由字符串分隔:@“\n\n”];
NSMutableArray*事件=[[NSMutableArray alloc]init];
[eventBuffer appendString:[子字符串objectAtIndex:0]];
//处理第一个事件-可以是部分
NSDictionary*json=(NSDictionary*)[eventBuffer JSONValue];
[events addObject:json];
对于(int i=1;i<[子字符串计数]-1;i++){
NSString*subString=[subStrings indexOfObject:i];
NSDictionary*eventJson=(NSDictionary*)[subString JSONValue];
[events addObject:eventJson];
}
//我们这里至少有一个项目要画
for(事件中的NSDictionary*事件){
NSLog(@“事件:%@,[event objectForKey:@“类型”]);
}
lastEvent=[events lastObject];
//清除事件缓冲区
[事件缓冲区设置字符串:@”“;
//是否将数据结尾添加到eventBuffer?
}否则{
[eventBuffer appendString:stringData];
}
//检查事件是否为程序退出事件,然后停止接收数据
如果([[lastEvent objectForKey:@“type”]比较:@“exit”]!=SensorDeredName){
//告诉文件句柄继续等待数据
[[note object]readInBackgroundAndNotify];
}否则{
NSLog(@“退出接收并停止接收数据”);
}
}

我以前遇到过这个问题。

读取完所有数据后,再进行一次“在后台接受连接”以再次读取数据。

Hmm,仍然不起作用,哦,好吧,我放弃了,只是用C中的标准套接字编写了它。尝试readInBackgroundAndNotify,而不是readInBackgroundAndNotify。我这样做了,这很有帮助。