My goal: Create a simple app, that connect to a TCP host, sends "Hello World" and closes the connection.
Being a complete beginner in iPhone development, my first step was check out the Apple's official Networking guides. I found and followed Cocoa Streams how-to. This document is filed under iPhone Reference, and can be accessed from the developer webpage. After hours of struggling with the seemingly simple code, I realized that iPhone OS does not support +getStreamsToHost:. I have filed a bug regarding this document's classification. After some chitchatting and more documentations, I found the correct way to create a connection is to use the CFNetwork framework, which is well explained by Apple here.
Following the sample code, I created an app that uses CFStreams to create a socket connection.
-(IBAction) connect_button {
CFWriteStreamRef writeStream = NULL;
CFStringRef host = CFSTR("10.212.97.159 ");
UInt32 port = 22701;
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, host, port, NULL, &writeStream);
CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
if(!CFWriteStreamOpen(writeStream)) {
NSLog(@"Error Opening Socket");
}
else{
UInt8 buf[] = "Hello WOrld!";
int bytesWritten = CFWriteStreamWrite(writeStream, buf, strlen((char*)buf));
NSLog(@"Written: %d", bytesWritten);
if (bytesWritten < 0) {
CFStreamError error = CFWriteStreamGetError(writeStream);
/** How do I print out description? All i get is -1 here. i.e What is perror() equivalent? **/
}
}
CFWriteStreamClose(writeStream);
}
Very simple and familiar looking code, so this should definitely work. Right? Well no it did not. I kept getting an error, which is stored in CFStreamError type. Problem is I had no way of interpreting that error. The CFError type is very well documented, but CFStreamError has a lot of loose ends. I spent quite a time trying to figure out what the error meant so that I could debug my application.
Update: The above code works! I still do not know how to print out the description of CFStreamError, but I found the error when I rewrote the code. The culprit is Line 5. Do you see it? :). Its the whitespace after the IP. Damn! That little error wasted atleast a few hours of my coding time.
Finally, I gave up on apple's way of networking and decided to do it the classic C-style way. I found an amazing library called the SmallSockets that uses the linux style of sockets under the hood, wrapped inside a Obj-C class. Downloaded it, added the headers file in my project and Voila!, it worked! All under 5 minutes!
-(IBAction) connect_button {
Socket *socket;
int port = 22701;
NSString *host = @"10.212.97.159";
socket = [Socket socket];
@try{
[socket connectToHostName:host port:port];
[socket writeString:@"Hello World!"];
//** Connection was successful **//
//[socket retain]; // Must retain if want to use out of this action block.
}
@catch (NSException* exception) {
NSString *errMsg = [NSString stringWithFormat:@"%@",[exception reason]];
NSLog(errMsg);
socket = nil;
}
//** Disconnect **//
[socket close];
}
Though my project is now up and running with 2-way network comm, I still want to get back to the CFNetwork and figure out where I went wrong, and try to implement a bare bone hello world app, the apple way.
5 comments:
i am getting 2 errors that read:
"error: 'Socket' undeclared (first use in function)"
"error: 'socket' undeclared (first use in function)"
any thoughts?
You need to include the SmallSockets libraries in your code. Basically #include or import. For that the library needs to be added to the project.
If you can post some code, I might be able to help.
Thanks!
in your first code, you need to release writeStream
Thank you for pointing that out!
Post a Comment