In a previous blog post, I took a look at how to create an Akka socket server using Akka IO that would read incoming messages in the form of Google Protocol Buffers. The information on the wire was framed so that it contained the length of the protobuf message as well as a numeric identifier telling my server which protobuf message.
Using a Scala client was a decent way of debugging things to figure out if my server code worked properly, but my real goal was to be able to send messages from an iPhone or iPad application to the Akka socket server. I continued to use the zombie sighting message that I created for the Akka server and for my “ProtoPhone” sample from this blog post here.
Now what I need to do is write some code in Objective-C that will send the protobuf messages over TCP via socket streams to the Akka server. The following code is not production ready, it’s just a brute force way of making sure that it works. In a real-world scenario there would be much more error handling, I wouldn’t send bytes on the NSStream until I got the “space available” message, etc.
NSInputStream *inputStream; NSOutputStream *outputStream; CFReadStreamRef readStream; CFWriteStreamRef writeStream; CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"localhost", 9999, &readStream, &writeStream); inputStream = (__bridge_transfer NSInputStream *)readStream; outputStream = (__bridge_transfer NSOutputStream *)writeStream; [inputStream setDelegate:self]; [outputStream setDelegate:self]; [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; // [inputStream open]; [outputStream open]; // Flip bytes for network order prior to transmission uint32_t length = (uint32_t)htonl([_rawZombie length]); uint32_t messageType = (uint32_t)htonl(1); // Keeping track of bytes written for debug purposes... int bytesWritten; bytesWritten = [outputStream write:(uint8_t *)&length maxLength:4]; NSLog(@"Wrote %d bytes to the stream", bytesWritten); bytesWritten = [outputStream write:(uint8_t *)&messageType maxLength:4]; NSLog(@"Wrote %d bytes to the stream", bytesWritten); // Write contents of protobuf object serialized as string, loaded into NSData pointer bytesWritten = [outputStream write:(uint8_t *)[_rawZombie bytes] maxLength:[_rawZombie length]]; NSLog(@"Wrote %d bytes to the stream", bytesWritten); [outputStream close];
This is pretty much all there is to it. As I mentioned, there’s some refactoring that needs to happen in order to deal with things like error handling and to better handle situations when I have to use multiple writes to send a single object (e.g. not enough space available on the stream), but you get the general idea.
I will be posting more on this as I go along, but for now, I am plenty happy with my shiny new toys of being able to communicate between an iOS client and an Akka server.