问题
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 NSStreamEventOpenCompleted
events 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.
回答1:
-[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."
来源:https://stackoverflow.com/questions/21503970/nsnetservice-publishes-but-didacceptconnectionwithinputstream-is-never-calle