2

我刚刚开始学习设计 iphone 应用程序,并且正在尝试设置客户端服务器环境。作为初学者,我想首先确保我发布的服务对客户端是可见的。我在 Apple 文档的帮助下编写了服务器和客户端代码。但是,我发现虽然我的服务正在发布(调用了 netServiceWillPublish(NSNetService *)sender),但我的客户端并未识别此服务。在客户端调用委托函数 netServiceBrowserWillSearch:(NSNetServiceBrowser *)browser 使我相信客户端正在搜索服务。但是 didFindService 委托函数永远不会被调用。我很困惑为什么这不起作用。我已经从各个地方遵循了客户端的示例代码,并且我的代码与他们的代码相匹配。

我还有以下问题

  1. 服务名称(随传输层协议一起提供)可以是任何字符串吗?还是必须在http://www.dns-sd.org/ServiceTypes.html中指定。除了服务发现之外,这还有什么目的。

  2. 当我在服务器端打印出 NSNetService 对象的详细信息时(在设置套接字并启动服务之后),主机名被打印为(null)并且没有显示地址。从技术上讲,当服务打开时,这些不应该设置为值吗?如果是的话,有人可以告诉我我的代码哪里出错了吗?

我已经附加了我的项目的客户端和服务器代码块,其中完成了服务的发布和浏览。非常感谢您的帮助,因为我一直在处理这个问题。

这是浏览服务的客户端的代码片段

NSNetServiceBrowser *serviceBrowser;
serviceBrowser = [[NSNetServiceBrowser alloc] init];
[serviceBrowser setDelegate:self];
[serviceBrowser searchForServicesOfType:@"_http._tcp." inDomain:@"local."];

这是发布服务的服务器端的代码片段

BOOL                success;
int                 fd;
int                 err;
int                 junk;
struct sockaddr_in  addr;
NSInteger           port;

port = 0;

fd = socket(AF_INET, SOCK_STREAM, 0);
success = (fd != -1);
if(success) {
    memset(&addr, 0, sizeof(addr));
    addr.sin_len = sizeof(addr);
    addr.sin_family = AF_INET;    
    addr.sin_port = 0;
    addr.sin_addr.s_addr = INADDR_ANY;
    err = bind(fd, (const struct sockaddr*) &addr, sizeof(addr));
    success = (err == 0);
}

if (success) {
    err = listen(fd, 5);
    success = (err == 0);
}

if (success) {
    socklen_t addrLen;
    addrLen = sizeof(addr);
    err = getsockname(fd, (struct sockaddr *) &addr, &addrLen);
    success = (err == 0);

    if (success) {
        assert( addrLen = sizeof(addr));
        port = ntohs(addr.sin_port);
    }
}

if (success) {
    CFSocketContext context = { 0, (__bridge void *) self, NULL, NULL, NULL };

    assert(self->_listeningSocket == NULL);
    self->_listeningSocket = CFSocketCreateWithNative(NULL, fd, kCFSocketAcceptCallBack, AcceptCallBack, &context);

    success = (self->_listeningSocket != NULL);

    if (success) {
        CFRunLoopSourceRef rls;
        fd = -1;    //listeningSocket is now responsible for closing the socket
        rls = CFSocketCreateRunLoopSource(NULL, self.listeningSocket, 0);
        assert(rls != NULL);
        CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
        CFRelease(rls);
    }
}

if (success) {
    self.netService = [[NSNetService alloc] initWithDomain:@"local." type:@"_http._tcp." name:@"test" port:port];
    success = (self.netService != nil);
}
if (success) {
    self.netService.delegate = self;
    [self.netService publishWithOptions:NSNetServiceNoAutoRename];

}

if (success) {
    assert(port != 0);
    [self serverDidStartOnPort:port];
}
else {
    [self stopServer:@"Start Failed"];
    if (fd != -1) {
        junk = close(fd);
        assert(junk == 0);
    }
}

这是告诉服务已发布并打印出我的 NSSocket 对象的详细信息的代码片段

- (void)netServiceWillPublish:(NSNetService *)sender {
    NSLog(@"This function is getting called");
    NSLog(@"sender.name %@",sender.name);
    NSLog(@"sender.addresses %@",sender.addresses);
    NSLog(@"sender.domain %@",sender.domain);
    NSLog(@"sender.hostname %@",sender.hostName);
    NSLog(@"sender.type %@",sender.type);
    NSLog(@"sender.port %d",sender.port);
}

谢谢维韦克
_

4

0 回答 0