I've been trying to make a simple app on iOS that will receive a message, and then perform an action based on that message (at the moment I just want to show it via NSLog). I can connect to the service, but the service never seems to receive anything. Here's my .h file:

#import <Foundation/Foundation.h>
#import <arpa/inet.h>

@interface PalServiceController : NSObject <NSNetServiceDelegate>

@property (nonatomic, strong) NSNetService *ns;
@property (nonatomic, strong) NSOutputStream *ostream;

- (void)start;
+ (int)getPort;
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode;

@end

and my .m:

#import "PalServiceController.h"

@implementation PalServiceController

- (void)start
{
    // Start a net service
    int port = [PalServiceController getPort];
    NSLog(@"Opening on port %i", port);
    self.ns = [[NSNetService alloc] initWithDomain:@""
                                              type:@"_TestingProtocol._tcp."
                                              name:@"Test Name For iPhone"
                                              port:port];
    if (self.ns) {
        [self.ns setDelegate:self];
        [self.ns publish];
        self.ns.delegate = self;
    } else {
        NSLog(@"Error starting service");
    }

}

/*
 * Code from: http://stackoverflow.com/a/11723158/657676
 */
+ (int) getPort
{
 ...   
}

- (void)netServiceWillResolve:(NSNetService *)sender
{
    NSLog(@"Resolving");
}

- (void)netServiceDidResolveAddress:(NSNetService *)sender
{
    NSLog(@"Resolved Address");
}

- (void)netService:(NSNetService *)sender didNotPublish:(NSDictionary *)errorDict
{
    NSLog(@"Error publishing");
}

- (void)netService:(NSNetService *)sender didAcceptConnectionWithInputStream:(NSInputStream *)inputStream outputStream:(NSOutputStream *)outputStream
{
    NSLog(@"Got a connection! (server)");
    // Close self down
    [self.ns stopMonitoring];
    [self.ns stop];
}

- (void)netService:(NSNetService *)sender didNotResolve:(NSDictionary *)errorDict
{
    NSLog(@"Error resolving");
}
- (void)netServiceDidPublish:(NSNetService *)sender
{
    NSLog(@"Published server");
}

- (void)netServiceDidStop:(NSNetService *)sender
{
    NSLog(@"Server stopped");
}

- (void)netService:(NSNetService *)sender didUpdateTXTRecordData:(NSData *)data
{
    NSLog(@"Updated TXT Record");
}

- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
{
    NSLog(@"Event on server");
    switch(eventCode) {
        ...
    }
}

@end

This is called via:

self.controller = [[PalServiceController alloc] init];
[self.controller start];

When I use Bonjour Browser, I can see the service, and when I use either my own implementation of an NSNetServiceBrowser or the example from Bill Dudney(blog post, code), it seems to connect (i.e. my own implementation receives the NSStreamEventHasSpaceAvailable and NSStreamEventOpenCompletedevents via stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode). However, none of the methods above get called on the server.

I'm still new to iOS, so I'm hoping that this is just some silly mistake that can be easily fixed.

有帮助吗?

解决方案

-[NSNetService publish] simply publishes the service; you're responsible for creating a socket and listening on the port you give to the NSNetService initializer. You won't receive netService:didAcceptConnectionWithInputStream:outputStream: because the NSNetService knows nothing about the socket.

If you want the NSNetService to manage the socket for you—and send didAcceptConnection...—use -[NSNetService publishWithOptions:]:

[self.ns publishWithOptions:NSNetServiceListenForConnections];

In this case, you need to make sure that the port with which you initialize the NSNetService is unused. Your getPort method never closes the socket (and leaks the CFSocketRef), so it will be in use when you publish the service, leading to an error.

I'd recommend that you remove getPort and, as Apple suggests in NSNetServices.h, "[s]pecify a port number of zero to use a random port."

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top