Using NSNetService class to make an SMB tcp ip connection to a folder shared on windows machine
Asked Answered
L

2

2

I have been trying to figure out a way to access my windows shared folder using iPhone. The desired functionality is part of bigger enterprise app I am building. Here is someone who has already asked a similar question but no luck - Does iOS support file operations via SMB?

Now, I have found apple developer tutorial called "SimpleNetworkStreams" which employs NSNetService to use x-SNSUpload protocol over tcp by setting type of NSNetService instance to protocol x-SNSUpload._tcp

Here is how they have done it -

self.netService = [[[NSNetService alloc] initWithDomain:@"local." type:@"_x-SNSUpload._tcp." name:@"Test"] autorelease];

So if I just replace _x-SNSUpload._tcp with _smb._tcp and run SMB server on my macbook. I run following set of commands to start SMB on my macbook

dns-sd -R Test _smb._tcp. "" 12345

nc -l 12345 > tmp.png

Then I am able to transfer a picture in my iPhone to my macbook's root directory. I was hoping to do the same with shared folder on windows machine.

The name of the share folder is "test sharing". I have explicitly shared my 'test sharing' folder in my windows machine with full control to everyone. The complete details of code is put below (after Update)

If I directly type in "smb:\\10.212.19.121" on my browser I am able to access my shared folder. It opens the finder application and gives me an option to mount the "temp sharing" folder.


Update - lot of redundant text taken out from above and better details on how SimpleNetworkStreams work and what I have tweaked is put below.

The code is taken from - SimpleNetworkStreams -

  1. Open the stream of type NSInputStream for the file we want to send
//Open a stream for the file we're going to send

//filepath is a NSString with path to the file on iPhone

self.fileStream = [NSInputStream inputStreamWithFileAtPath:filepath]; 

assert(self.fileStream != nil); 

[self.fileStream open];
  1. As how apple documentation says

"you can either create an NSNetService object directly (if you know the exact host and port information) or you can use an NSNetServiceBrowser object to browse for services. "

An object of NSNetService is instantiated for the server which hosts SMB server

// 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]];
 

Get the output stream object of type NSOutputStream into self.networkStream.

success = [self.netService getInputStream:NULL outputStream:&output];
assert(success);

self.networkStream = output;

[output release];

self.networkStream.delegate = self;
[self.networkStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

[self.networkStream open];

and then the NSOutputStream delegate catches NSStreamEventHasSpaceAvailable where we buffer in the input file and then write that buffer to our NSOutputStream object i.e. networkStream

bytesWritten = [self.networkStream write:&self.buffer[self.bufferOffset] maxLength:self.bufferLimit - self.bufferOffset];
Lisbethlisbon answered 12/2, 2011 at 0:36 Comment(0)
B
2

I think you misunderstood NSNetservice. NSNetService can be used to publish Bonjour Information about network services in your network. It doesn't create a server for you, it just tells the clients that there is a server with the service available. Even if there is no such server it will tell the client that there is one.

Try bonjour browser to see what NSNetService does. All the entries you will see are published NSNetServices.
Or you could publish a service with the type _afpovertcp._tcp. and watch the sidebar in finder to get an idea how NSNetServices are used.


dns-sd -R Test _smb._tcp. "" 12345
nc -l 12345 > tmp.png

These lines have absolutely nothing to do with SMB. Just because you are advertising your service as SMB doesn't mean that your server actually understands SMB.
And nc (aka netcat) does exactly what its name suggests. It dumps everything you send to it into your file. Not SMB, not at all.

And using TXTRecords for Authentication is a bad idea, everybody who is connected to your network will get the TXTRecords.

To make a long story short, NSNetServices won't help you with creating SMB connections. Once you are done with the SMB Server you can use NSNetServices to tell clients in your network that there is a SMB Server. But it won't help you in creating this server.

Bacchae answered 5/3, 2011 at 7:55 Comment(7)
@fluchtpunkt I am not creating a SMB server using NSNetService. I am able to use smb:\\10.212.19.121 from my browser in macbook to connect to windows shared folder (10.212.19.121 being the ip address of windows m/c).It also authenticates me when I connect. So SMB service is already running. I want to use NSNetService object within iPhone as a client to connect 10.212.19.121 m/c & for that I am using self.netService = [[[NSNetService alloc] initWithDomain:@"10.212.19.121" type:@"_smb._tcp." name:@"lanmanserver"] autorelease];.I am setting TXTRecords in a local client NSNetService object..Lisbethlisbon
NSNetService is neither client nor server. It has nothing to do with SMB. If you want to discover SMB-Servers you could use NSNetServiceBrowser, but you have to implement the smb client on your own. And if a NSNetService is local (ie not published) than there is no reason that it exists. You are completely misunderstanding the use of NSNetService. It can only be used for "Hello, I can understand this protocol, please connect at this ip and this port"-broadcasts. Nothing which is related to the actual server or client. You have to implement those on your own.Bacchae
@fluchtpunkt There might be some confusion as to what you think I am trying to do. I have tried to make the question more self explanatory. Thanks for your responseLisbethlisbon
ok, didn't know that you can create a remote NSNetService manually, but makes sense. So now you have a connection to the server, but this is just like a dumb pipe. What you put in on one end comes out exactly the same on the other side. But the other side understands only smb, what you don't speak. So now you have to implement smb protocol. The server resolution and opening the in- and outputstreams is a beginning, but it's like 1% from what is needed to transfer files to or from smb. You can't just push files into the networkstream. You have to encapsulate your files into smb messages.Bacchae
@fluchtpunkt Thats exactly what I am hoping this NSNetService will do for me since I have the output stream from it and have created this NSNetService by mentioning that I want you to follow SMB protocol instead of SNS tcp protocol. Nevertheless, any ideas why it worked between iPhone simulator and macbook and not between iPhone simulator and windows machine. The macbook was advertising smb protocol and I used iPhone simulator to send over the image using _smb._tcp. .. I tried looking places to understand what exactly SNS meant. Any ideas on that too?Lisbethlisbon
It didn't work between iphone and macbook. At least not over smb, you've used netcat. And you redirected netcat output into a file. If you install cygwin and netcat on windows you could do the same. But this has nothing to do with smb. SNS is just apples arbitrary name for the service they wrote. You can name those services like you want. They are just names. You publish a NSNetservice on the server with a arbitrary type _foo._tcp. and on the client you start a search with NSNetServiceBrowser for the same type.Bacchae
@fluchtpunkt just one final question.. what values can we provide for the parameter 'type' in following line of code self.netService = [[[NSNetService alloc] initWithDomain:@"10.212.19.121" type:@"_smb._tcp." name:@"lanmanserver"] autorelease];Lisbethlisbon
M
1

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

Mairemaise answered 5/3, 2011 at 6:52 Comment(1)
I am pretty sure on @fluchtpunkt answers and comments. This NSNetService doesn't do the SMB packaging for you. However, I did try out your suggestion. Didn't work. thanks for replying ..Lisbethlisbon

© 2022 - 2024 — McMap. All rights reserved.