Showing posts with label NSNetService. Show all posts
Showing posts with label NSNetService. Show all posts

Friday, June 21, 2013

NSNetService initWithDomain example in Objective C (iOS).


NSNetService initWithDomain

Returns the receiver, initialized as a network service of a given type and sets the initial host information.

- (id)initWithDomain:(NSString *)domain type:(NSString *)type name:(NSString *)name

Parameters of [NSNetService initWithDomain]
domain
The domain for the service. For the local domain, use @"local." not @"".
type
The network service type.
type must contain both the service type and transport layer information. To ensure that the mDNS responder searches for services, as opposed to hosts, prefix both the service name and transport layer name with an underscore character (“_”). For example, to search for an HTTP service on TCP, you would use the type string "_http._tcp.". Note that the period character at the end of the string, which indicates that the domain name is an absolute name, is required.
name
The name of the service to resolve.

Return Value of [NSNetService initWithDomain]
The receiver, initialized as a network service named name of type type in the domain domain.

Discussion of [NSNetService initWithDomain]
This method is the appropriate initializer to use to resolve a service—to publish a service, use initWithDomain:type:name:port:.

If you know the values for domain, type, and name of the service you wish to connect to, you can create an NSNetService object using this initializer and call resolveWithTimeout: on the result.

You cannot use this initializer to publish a service. This initializer passes an invalid port number to the designated initializer, which prevents the service from being registered. Calling publish on an NSNetService object initialized with this method generates a call to your delegate’s netService:didNotPublish: method with an NSNetServicesBadArgumentError error.

NSNetService initWithDomain example.
I'm not sure, but it looks like the request is not actually scheduled in a run loop for some reason. Maybe try something like this to schedule it?

NSNetService *service = [[[NSNetService alloc] initWithDomain:@"local." type:@"_daap._tcp." name:@"My_Mac"] autorelease];
[service setDelegate:self];
[service scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:@"PrivateMyMacServiceMode"];
[service resolveWithTimeout:8.0];
Stupid question, but are you explicitly implementing NSServiceDelegate protocol or just have the methods?

Example of [NSNetService initWithDomain].
conclusion: publish by first obtaining a port and then use something like:

self.netService = [[NSNetService alloc] initWithDomain:@"local" type:@"_xxx._tcp." name:serviceName port:(int) self.port];
open streams with
CFStreamCreatePairWithSocket(kCFAllocatorDefault, nativeSocketHandle, &readStream, &writeStream);
open streams with (you open a connection here)
EchoConnection * connection = [[EchoConnection alloc] initWithInputStream:( NSInputStream *)readStream outputStream:( NSOutputStream *)writeStream];
        [self.connections addObject:connection];
then browse for services and add them

then open streams on the desired services from the one you browsed with

[nService qNetworkAdditions_getInputStream:&istream outputStream:&ostream];
(and open them with [istream open] and [ostream open])

NSNetService initWithDomain example.
#import "ServerController.h"

@interface ServerController ()

-(void)startService;
-(void)stopService;

@end

@implementation ServerController

-(void)awakeFromNib {   
    [self startService];
}

-(void)startService {
    netService = [[NSNetService alloc] initWithDomain:@"" type:@"_cocoaforsci._tcp."
        name:@"" port:7865];
    netService.delegate = self;
    [netService publish];
}

-(void)stopService {
    [netService stop];
    [netService release];
    netService = nil;
}

-(void)dealloc {
    [self stopService];
    [super dealloc];
}

#pragma mark Net Service Delegate Methods
-(void)netService:(NSNetService *)aNetService didNotPublish:(NSDictionary *)dict {
    NSLog(@"Failed to publish: %@", dict);
}

@end

End of NSNetService initWithDomain example article.

NSNetService initWithDomain type name example in Objective C (iOS).


NSNetService initWithDomain type name

Returns the receiver, initialized as a network service of a given type and sets the initial host information.

- (id)initWithDomain:(NSString *)domain type:(NSString *)type name:(NSString *)name

Parameters of [NSNetService initWithDomain type name]
domain
The domain for the service. For the local domain, use @"local." not @"".
type
The network service type.
type must contain both the service type and transport layer information. To ensure that the mDNS responder searches for services, as opposed to hosts, prefix both the service name and transport layer name with an underscore character (“_”). For example, to search for an HTTP service on TCP, you would use the type string "_http._tcp.". Note that the period character at the end of the string, which indicates that the domain name is an absolute name, is required.
name
The name of the service to resolve.

Return Value of [NSNetService initWithDomain type name]
The receiver, initialized as a network service named name of type type in the domain domain.

Discussion of [NSNetService initWithDomain type name]
This method is the appropriate initializer to use to resolve a service—to publish a service, use initWithDomain:type:name:port:.

If you know the values for domain, type, and name of the service you wish to connect to, you can create an NSNetService object using this initializer and call resolveWithTimeout: on the result.

You cannot use this initializer to publish a service. This initializer passes an invalid port number to the designated initializer, which prevents the service from being registered. Calling publish on an NSNetService object initialized with this method generates a call to your delegate’s netService:didNotPublish: method with an NSNetServicesBadArgumentError error.

NSNetService initWithDomain type name example.
I'm not sure, but it looks like the request is not actually scheduled in a run loop for some reason. Maybe try something like this to schedule it?

NSNetService *service = [[[NSNetService alloc] initWithDomain:@"local." type:@"_daap._tcp." name:@"My_Mac"] autorelease];
[service setDelegate:self];
[service scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:@"PrivateMyMacServiceMode"];
[service resolveWithTimeout:8.0];
Stupid question, but are you explicitly implementing NSServiceDelegate protocol or just have the methods?

Example of [NSNetService initWithDomain type name].
conclusion: publish by first obtaining a port and then use something like:

self.netService = [[NSNetService alloc] initWithDomain:@"local" type:@"_xxx._tcp." name:serviceName port:(int) self.port];
open streams with
CFStreamCreatePairWithSocket(kCFAllocatorDefault, nativeSocketHandle, &readStream, &writeStream);
open streams with (you open a connection here)
EchoConnection * connection = [[EchoConnection alloc] initWithInputStream:( NSInputStream *)readStream outputStream:( NSOutputStream *)writeStream];
        [self.connections addObject:connection];
then browse for services and add them

then open streams on the desired services from the one you browsed with

[nService qNetworkAdditions_getInputStream:&istream outputStream:&ostream];
(and open them with [istream open] and [ostream open])

NSNetService initWithDomain type name example.
#import "ServerController.h"

@interface ServerController ()

-(void)startService;
-(void)stopService;

@end

@implementation ServerController

-(void)awakeFromNib {   
    [self startService];
}

-(void)startService {
    netService = [[NSNetService alloc] initWithDomain:@"" type:@"_cocoaforsci._tcp."
        name:@"" port:7865];
    netService.delegate = self;
    [netService publish];
}

-(void)stopService {
    [netService stop];
    [netService release];
    netService = nil;
}

-(void)dealloc {
    [self stopService];
    [super dealloc];
}

#pragma mark Net Service Delegate Methods
-(void)netService:(NSNetService *)aNetService didNotPublish:(NSDictionary *)dict {
    NSLog(@"Failed to publish: %@", dict);
}

@end

End of NSNetService initWithDomain type name example article.

NSNetService hostName example in Objective C (iOS).


NSNetService hostName

Returns the host name of the computer providing the service.

- (NSString *)hostName

Return Value of [NSNetService hostName]
The host name of the computer providing the service. Returns nil if a successful resolve has not occurred.

NSNetService hostName example.
I believe that "hows-testing" is the host name of the computer, not the name of the service. Instead, you want to look at the hostName attribute:

- (void)netServiceDidPublish:(NSNetService *)ns
{
   NSLog(@"Bonjour Service Published: http://%@", [ns hostName]);
}
You should probably also examine the port attribute, and include it in the URL, if the port is something other than the default for that protocol (80 for HTTP)

End of NSNetService hostName example article.

NSNetService getInputStream outputStream example in Objective C (iOS).


NSNetService getInputStream outputStream

Retrieves by reference the input and output streams for the receiver and returns a Boolean value that indicates whether they were retrieved successfully.

- (BOOL)getInputStream:(NSInputStream **)inputStream outputStream:(NSOutputStream **)outputStream

Parameters
inputStream
Upon return, the input stream for the receiver.
outputStream
Upon return, the output stream for the receiver.

Return Value
YES if the streams are created successfully, otherwise NO.

Discussion of [NSNetService getInputStream outputStream]
After this method is called, no delegate callbacks are called by the receiver.

NSNetService getInputStream outputStream example.
Don't believe everything apple claims,

There are a lot of problems with setting up streams with the NSNetworkService.

It will work if you do the following:

First obtain a port to publish the network on. DO NOT PICK A PORT YOURSELF.

Then you can use that port for publishing the network.

Get the client streams with:

[nService qNetworkAdditions_getInputStream:&istream outputStream:&ostream];
The error a lot of programmers make is publishing a network by picking a port themselves and then opening the streams with

[nService qNetworkAdditions_getInputStream:&istream outputStream:&ostream];
The streams will not open....

conclusion: publish by first obtaining a port and then use something like:

self.netService = [[NSNetService alloc] initWithDomain:@"local" type:@"_xxx._tcp." name:serviceName port:(int) self.port];
open streams with
CFStreamCreatePairWithSocket(kCFAllocatorDefault, nativeSocketHandle, &readStream, &writeStream);
open streams with (you open a connection here)
EchoConnection * connection = [[EchoConnection alloc] initWithInputStream:( NSInputStream *)readStream outputStream:( NSOutputStream *)writeStream];
        [self.connections addObject:connection];
then browse for services and add them

then open streams on the desired services from the one you browsed with

[nService qNetworkAdditions_getInputStream:&istream outputStream:&ostream];
(and open them with [istream open] and [ostream open])

Example of [NSNetService getInputStream outputStream].
I have just changed my method as below

NSInputStream  *tempInput  = nil;
NSOutputStream *tempOutput = nil;

// note the following method returns _inStream and _outStream with a retain count that the caller must eventually release
if (![netService getInputStream:&tempInput outputStream:&tempOutput]) {

    NSLog(@"error in get input and output streams");
    return;
}
_inStream  = tempInput;
_outStream = tempOutput;

NSNetService getInputStream outputStream example.
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
 if (inputStream && outputStream) [self closeStreams];
   
 if (indexPath.row) {
NSNetService * selectedService = [serviceList objectAtIndex:indexPath.row];
if ([selectedService getInputStream:&inputStream outputStream:&outputStream]) [self openStreams];
serverLabel.text = [[serviceList objectAtIndex:indexPath.row] name];
}
 }

End of NSNetService getInputStream outputStream example article.

NSNetService getInputStream example in Objective C (iOS).


NSNetService getInputStream

Retrieves by reference the input and output streams for the receiver and returns a Boolean value that indicates whether they were retrieved successfully.

- (BOOL)getInputStream:(NSInputStream **)inputStream outputStream:(NSOutputStream **)outputStream

Parameters
inputStream
Upon return, the input stream for the receiver.
outputStream
Upon return, the output stream for the receiver.

Return Value
YES if the streams are created successfully, otherwise NO.

Discussion of [NSNetService getInputStream]
After this method is called, no delegate callbacks are called by the receiver.

NSNetService getInputStream example.
Don't believe everything apple claims,

There are a lot of problems with setting up streams with the NSNetworkService.

It will work if you do the following:

First obtain a port to publish the network on. DO NOT PICK A PORT YOURSELF.

Then you can use that port for publishing the network.

Get the client streams with:

[nService qNetworkAdditions_getInputStream:&istream outputStream:&ostream];
The error a lot of programmers make is publishing a network by picking a port themselves and then opening the streams with

[nService qNetworkAdditions_getInputStream:&istream outputStream:&ostream];
The streams will not open....

conclusion: publish by first obtaining a port and then use something like:

self.netService = [[NSNetService alloc] initWithDomain:@"local" type:@"_xxx._tcp." name:serviceName port:(int) self.port];
open streams with
CFStreamCreatePairWithSocket(kCFAllocatorDefault, nativeSocketHandle, &readStream, &writeStream);
open streams with (you open a connection here)
EchoConnection * connection = [[EchoConnection alloc] initWithInputStream:( NSInputStream *)readStream outputStream:( NSOutputStream *)writeStream];
        [self.connections addObject:connection];
then browse for services and add them

then open streams on the desired services from the one you browsed with

[nService qNetworkAdditions_getInputStream:&istream outputStream:&ostream];
(and open them with [istream open] and [ostream open])

Example of [NSNetService getInputStream].
I have just changed my method as below

NSInputStream  *tempInput  = nil;
NSOutputStream *tempOutput = nil;

// note the following method returns _inStream and _outStream with a retain count that the caller must eventually release
if (![netService getInputStream:&tempInput outputStream:&tempOutput]) {

    NSLog(@"error in get input and output streams");
    return;
}
_inStream  = tempInput;
_outStream = tempOutput;

NSNetService getInputStream example.
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
 if (inputStream && outputStream) [self closeStreams];
   
 if (indexPath.row) {
NSNetService * selectedService = [serviceList objectAtIndex:indexPath.row];
if ([selectedService getInputStream:&inputStream outputStream:&outputStream]) [self openStreams];
serverLabel.text = [[serviceList objectAtIndex:indexPath.row] name];
}
 }

End of NSNetService getInputStream example article.

NSNetService addresses example in Objective C (iOS).


NSNetService addresses

Returns an array containing NSData objects, each of which contains a socket address for the service.

- (NSArray *)addresses

Return Value
An array containing NSData objects, each of which contains a socket address for the service. Each NSData object in the returned array contains an appropriate sockaddr structure that you can use to connect to the socket. The exact type of this structure depends on the service to which you are connecting. If no addresses were resolved for the service, the returned array contains zero elements.

Discussion of [NSNetService addresses]
It is possible for a single service to resolve to more than one address or not resolve to any addresses. A service might resolve to multiple addresses if the computer publishing the service is currently multihoming.

NSNetService addresses example.
for (NSData* data in [server addresses]) {

    char addressBuffer[100];

    struct sockaddr_in* socketAddress = (struct sockaddr_in*) [data bytes];

    int sockFamily = socketAddress->sin_family;

    if (sockFamily == AF_INET || sockFamily == AF_INET6) {

        const char* addressStr = inet_ntop(sockFamily,
                            &(socketAddress->sin_addr), addressBuffer,
                            sizeof(addressBuffer));

        int port = ntohs(socketAddress->sin_port);

        if (addressStr && port)
            NSLog(@"Found service at %s:%d", addressStr, port);

    }

}

Example of [NSNetService addresses].
for (NSData *address in [service addresses]) {
struct sockaddr_in *socketAddress = (struct sockaddr_in *) [address bytes];
            NSLog(@\"Service name: %@ , ip: %s , port %i\", [service name], inet_ntoa(socketAddress->sin_addr), [service port]);
        }

NSNetService addresses example.
@implementation NSNetService (ipv4)

- (NSArray*)ipv4addresses
{
        NSMutableArray * ipv4addresses = [NSMutableArray array];
        NSArray *addresses = [self addresses];
        int aCount = [addresses count];
        char addr[256];
       
        for (int i = 0; i < aCount; i++) {
                struct sockaddr *socketAddress = (struct sockaddr *)[[addresses 
objectAtIndex:i] bytes];
               
                if (socketAddress && socketAddress->sa_family == AF_INET) {
                        if (inet_ntop(AF_INET, &((struct sockaddr_in *)socketAddress)-
 >sin_addr, addr, sizeof(addr))) {
                               
                                uint16_t port = ntohs(((struct sockaddr_in *)socketAddress)-
 >sin_port);
                               
                                [ipv4addresses addObject:[NSString stringWithFormat:@"%s:%d", 
addr, port]];
                        }
                }
        }
       
        return ipv4addresses;
}

@end


End of NSNetService addresses example article.

NSNetService dataFromTXTRecordDictionary example in Objective C (iOS).


NSNetService dataFromTXTRecordDictionary

Returns an NSData object representing a TXT record formed from a given dictionary.

+ (NSData *)dataFromTXTRecordDictionary:(NSDictionary *)txtDictionary

Parameters
txtDictionary
A dictionary containing a TXT record.

Return Value of [NSNetService dataFromTXTRecordDictionary]
An NSData object representing TXT data formed from txtDictionary. Fails an assertion if txtDictionary cannot be represented as an NSData object.
NSNetService dataFromTXTRecordDictionary example.
NSImage *original = [NSImage imageNamed:NSImageNameComputer];
                [original setSize:NSMakeSize(10.0f, 10.0f)];
                NSData *image = [original TIFFRepresentation];
                NSBitmapImageRep *imageRep = [NSBitmapImageRep 
imageRepWithData:image];
                NSData *finalData = [imageRep representationUsingType:NSPNGFileType 
properties:nil];
                NSDictionary *txtRecord = [NSDictionary 
dictionaryWithObject:finalData forKey:@"image"];
                NSData *data = [NSNetService dataFromTXTRecordDictionary:txtRecord];
                if (data)
                        NSLog(@"Data is not nil!");
                [netService setTXTRecordData:data];


Example of [NSNetService dataFromTXTRecordDictionary].
// Open a stream to the server, finding the server via Bonjour.  Then configure
// the stream for async operation.

//here's the tweak.
//original code looked like -
//self.netService = [[[NSNetService alloc] initWithDomain:@"local." type:@"_x-SNSUpload._tcp." name:@"Test"] autorelease];

self.netService = [[[NSNetService alloc] initWithDomain:@"10.212.19.121" type:@"_smb._tcp." name:@"lanmanserver"] autorelease];

assert(self.netService != nil);

NSDictionary *newDict = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObjects:@"domain\\username",@"password",@"C:\\Documents and Settings\\username\\Desktop\\test%20sharing",nil] forKeys:[NSArray arrayWithObjects:@"u",@"p",@"path",nil]];

[self.netService setTXTRecordData:[NSNetService dataFromTXTRecordDictionary:newDict]];

NSNetService dataFromTXTRecordDictionary example.
NSDictionary *txt = [NSDictionary dictionaryWithObjectsAndKeys:
    [@"1" dataUsingEncoding:NSUTF8StringEncoding], @"txtvers",
    [@"131073" dataUsingEncoding:NSUTF8StringEncoding], @"iTSh Version",
    [@"196610" dataUsingEncoding:NSUTF8StringEncoding], @"Version",
    nil];

NSData *txtData = [NSNetService dataFromTXTRecordDictionary:txt];

[bonjourServer setTXTRecordData:txtData];

End of NSNetService dataFromTXTRecordDictionary example article.