How to define a communication protocol? - cocoa-touch

I'm new to networking concepts and need an explaination of how to implement a communication protocol for sending different types of messages. I'm currently working on a Cocoa app that will send video messages between iPhones. Currently I only send messages of type 3. Here's the app flow I need to implement:
Browsing for available iPhones on the network (using Bonjour)
When an iPhone client is found, send NSData "request contact info" (MessageType1)
iPhone client will send back an NSData instance with contact info (MessageType2)
Init a new message with recorded video, send to selected contact (MessageType3)
When the different types of message are received, they will need to be handled differently. I guess one way to solve it is to add a header to the message that identify the message type and extract this on the receiver's side, then handle like this:
if (messageType == 1) // MessageType1
[self sendMyContactInfo:(Contact *)ownInfo];
if (messageType == 2) // MessageType2
[self updateViewWithContactInfo:(Contact *)contactInfo];
if (messageType == 3) // MessageType3
[self sendMessageToSelectedContact:(Message *)message]
For creating a message for MessageType3, I'll do this:
/* Not currently implemented */
NSMutableData *data = [[NSMutableData alloc] init];
int messageType = 3;
[data appendBytes:messageType]
/* Already Implemented */
NSData *encodedMessage = [NSKeyedArchiver archivedDataWithRootObject:message];
[data appendData:encodedMessage];
[self sendMessage:(NSData *)encodedMessage];
Is this a nice way of doing it? If so, should the protocol rules be defined in a more formal way, e.g. in a separate class or something? I'm looking for the best overall solution here, so don't take too much notice of my drawings if there's a better way to do it...

Is this a nice way of doing it?
It's a standard way for defining a communications protocol. From the Wikipedia article:
Digital message bitstrings are exchanged. The bitstrings are divided in fields and each field carries information relevant to the protocol. Conceptually the bitstring is divided into two parts called the header area and the data area. The actual message is stored in the data area, so the header area contains the fields with more relevance to the protocol. The transmissions are limited in size, because the number of transmission errors is proportional to the size of the bitstrings being sent. Bitstrings longer than the maximum transmission unit (MTU) are divided in pieces of appropriate size. Each piece has almost the same header area contents, because only some fields are dependent on the contents of the data area (notably CRC fields, containing checksums that are calculated from the data area contents).
End Wikipedia quote
If so, should the protocol rules be defined in a more formal way, e.g. in a separate class or something?
That's up to you. It's not necessary, since your application is communicating with other copies of your application.

Related

Bluetooth Core Framework callback routine peripheralManagerIsReadyToUpdateSubscribers: isn't called

I'm trying to figure out how to make certain callbacks trigger.
On the peripheral peripheralManager:central:didSubscribeToCharacteristic: is called correctly and it sends a chunk (first of two) of data to the central which receives it in peripheral:didUpdateValueForCharacteristic:error: as expected.
Now there's one chunk left which is supposed to be sent in the peripheral's callback peripheralManagerIsReadyToUpdateSubscribers: according to Apple's test application.
I've tested and verified and it works fine there. It's a bit fishy though as according to the docs it's only supposed to be called when the peripheral manager's updateValue:forCharacteristic:onSubscribedCentrals: fails.
How do I make the peripheral send the remaining chunk? I can supply you with code, but it's almost identical (I'm using an array of NSData chunks instead of one large NSData like the example) to the example application I linked to, I'm more curious as to how the callback chain works and what needs to be in place for the different selectors to trigger.
What you are doing is the normal way of operation. The peripheral manager handles the data sending and implements flow control according to the current settings. E.g. if you are using indications instead of notifications, then each update has to be acknowledged by the receiver before you can send again.
Notifications on the other hand are similar to UDP packets. They can get lost. To make sure that the data arrived error free, you need to implement additional control flow management.
All in all, you are doing it right.
I managed to trigger peripheralManagerIsReadyToUpdateSubscribers: by using a loop in sendData (which is called from peripheralManagerIsReadyToUpdateSubscribers: and peripheralManager:central:didSubscribeToCharacteristic:).
- (void)sendData {
BOOL success = YES;
while (success && ([_outgoingDataQueue count] > 0)) {
NSData *chunk = [_outgoingDataQueue peek];
success = [self.peripheralManager updateValue:chunk
forCharacteristic:self.characteristic
onSubscribedCentrals:nil];
if (success) {
[_outgoingDataQueue dequeue];
}
}
}
This does not feel like the correct way to send data as chunks to the central.

Design suggestions for client receiving messages over network

I'm programming a client that receives a set of different messages from a server via TCP. I have created a simple test class that is able to connect to the server and receive messages in form of NSData chunks. But now I'm stuck at how to proceed from here and need some design suggestions.
One idea I have is to create a protocol that for each message, notifies the delegate with the type of message received and an object containing the message:
Protocol
-(void)didReceiveLifesign:(LifesignMessage*)message;
-(void)didReceiveLocation:(LocationMessage*)message;
...
Parser
-(void)didReceiveData:(NSData*)data {
int type = getType(data);
switch(type) {
case 0: [self.delegate didReceiveLifesign:parseLifesign(data); break;
case 1: [self.delegate didReceiveLocation:parseLocation(data); break;
...
}
}
But as the amount of messages grow I find this solution messy. Is there a prettier way of doing this?
Each time you add a new type of message to the system, you will be adding new code to handle that particular type. You cannot get away from that. So, the place you can really abstract-out right now is the dispatching: the switch statement, in your case.
If very few new message-types will be added in the future, the simplest approach may be the one you have already taken: simply add a new "case" each time.
An alternate approach is to allow other code to register as a "listener"/"callback". That makes the dispatching generic. The logic becomes:
Find the message type
Dispatch to all registered callbacks/listeners
The new "problem" would be: you will now need to register each listener at some point. This would be sdone during some type of initialization. it may not be worth it if your message dispatcher is basically part of the overall app, and is not to be used elsewhere.

How to send objects over tcp efficiently

Okay, so my goal is to build a easy to use protocol for sending data over tcp. basically, it would send a message, and an object(of unknown type) over tcp. To send, it would only require one method call and to receive it would only require one also.
So this is how I was thinking to format the "message".
length_of_message - "A string that is a message" - length_of_Object - object
length_of_message would be a set number of bytes. along with length_of_Object.
the actual message string and the actual object would be of variable length.
If the actual class of the object wouldn't be know, could I just declare it as a "generic object" somehow? and then get its class name from the "generic object" and the message would tell the receiver what to do with the object?
It would be simple if it was a constant object type but i want to be able use one send function and one receive function for ever object that needs to be send/recieved.
Any suggestions?
Thanks,
Andrew
Make sure you aren't reinventing the wheel (unless doing so is your primary goal).
With that in mind, consider:
• Implement and use the NSCoding protocol. It allows for the efficient archival of complexly connected object graphs, including cycles.
• Instead of raw TCP, use HTTP. While it adds a bit over overhead in the headers, the body can be straight encoded data. More importantly, HTTP is ubiquitous. It routes through just about anything whereas other protocols might be blocked (think proxy servers).
• Via HTTP, you can leverage compression. If one side of your communication pipe is an existing web server of some kind, it probably already supports gzip'd communication. Compressing an NSData (that would be the result of NSCoding) is trivial.
• Alternatively, stick with straight plists.
Unless you truly have some requirement that makes the above inviable, you are likely better off leveraging the above technologies instead of rolling a new one.
With that said, what you propose is fine. I would add, possibly, a structure like:
[HEADER][MSGID][LEN][TYPE][DATA of len][POST]
Where the POST is a known sequence of bytes that the receiver can verify to make sure that, maybe, all the data was received correctly. Or you could go whole hog and integrate a checksum. Or sub-pieces could be repeated, as needed (i.e. [LEN][TYPE][DATA] over and over.

NSURLConnection vs. NSData + GCD

NSData has always had a very convenient method called +dataWithContentsOfURL:options:error:. While convenient, it also blocks execution of the current thread, which meant it was basically useless for production code (Ignoring NSOperation). I used this method so infrequently, I completely forgot that it existed. Until recently.
The way I've been grabbing data from the tubes is the standard NSURLConnectionDelegate approach: Write a download class that handles the various NSURLConnectionDelegate methods, gradually build up some data, handle errors, etc. I'll usually make this generic enough to be reused for as many requests as possible.
Say my typical downloader class runs somewhere in the ballpark of 100 lines. That's 100 lines to do asynchronously what NSData can do synchronously in one line. For more complexity, that downloader class needs a delegate protocol of its own to communicate completion and errors to its owner, and the owner needs to implement that protocol in some fashion.
Now, enter Grand Central Dispatch, and I can do something as fantastically simple as:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
NSData* data = [NSData dataWithContentsOfURL:someURL];
// Process data, also async...
dispatch_async(dispatch_get_main_queue(), ^(void) {
// Back to the main thread for UI updates, etc.
});
});
And I can throw that sucker in anywhere I want, right in-line. No need for a download class, no need to handle connection delegate methods: Easy async data in just a few lines. The disparity between this approach and my pre-GCD approach is of a magnitude great enough to trigger the Too Good to be True Alarm.
Thus, my question: Are there any caveats to using NSData + GCD for simple data download tasks instead of NSURLConnection (Assuming I don't care about things like download progress)?
You are losing a lot of functionality here:
Can't follow the download progression
Can't cancel the download
Can't manage the possible authentication process
You can't handle errors easily, which is really important especially in mobile development like on iPhone of course (because you often lose your network in real conditions, so it is very important to track such network error cases when developing for iOS)
and there's probably more I guess.
The right approach for that is to create a class than manages the download.
See my own OHURLLoader class for example, which is simple and I made the API to be easy to use with blocks:
NSURL* url = ...
NSURLRequest* req = [NSURLRequest requestWithURL:url];
OHURLLoader* loader = [OHURLLoader URLLoaderWithRequest:req];
[loader startRequestWithCompletion:^(NSData* receivedData, NSInteger httpStatusCode) {
NSLog(#"Download of %# done (statusCode:%d)",url,httpStatusCode);
if (httpStatusCode == 200) {
NSLog(%#"Received string: %#", loader.receivedString); // receivedString is a commodity getter that interpret receivedData using the TextEncoding specified in the HTTP response
} else {
NSLog(#"HTTP Status code: %d",httpStatusCode); // Log unexpected status code
}
} errorHandler:^(NSError *error) {
NSLog(#"Error while downloading %#: %#",url,error);
}];
See the README file and sample project on github for more info.
This way:
you still rely on the asynchronous methods provided by NSURLConnection (and as the Apple's documentation says about Concurrency Programming if an API already exists to make asynchronous tasks, use it instead of relying on another threading technology if possible)
you keep advantages of NSURLConnection (error handlings, etc)
but you also have the advantages of the blocks syntax that makes your code more readable than when using delegate methods
WWDC 2010 Session Videos:
WWDC 2010 Session 207 - Network Apps for iPhone OS, Part 1
WWDC 2010 Session 208 - Network Apps for iPhone OS, Part 2
The lecturer said
"Threads Are Evil™".
For network programming, it is strongly recommended to use asynchronous API with RunLoop.
Because, if you use NSData + GCD like the following, it uses one thread per connection.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
NSData* data = [NSData dataWithContentsOfURL:someURL];
And it's likely to use many connections and many threads. It is too easy to use GCD :-)
Then, many threads eats huge amount of memory for its stack.
Thus, you'd better to use asynchronous API as AliSoftware said.
As of OS X v10.9 and iOS 7 the preferred way is to use NSURLSession. It gives you a nice, block-based interface and features like canceling, suspending and background downloading.

Is it better create a library with several functions or create classes?

I'm developing a software to comunicate with a device.
The software will send commands for the device. The device has to answer using the protocol below:
<STX><STX><COMMAND>[<DATA_1><DATA_2>...<DATA_N>]<CHKSUM><ETX>
where:
<STX> is the Start of TeXt (0x55);
<COMMAND> can be 0x01 for read, 0x02 for write, etc;
<DATA> is any value;
<CHKSUM> is the checksum;
<ETX> is the End of TeXt (0x04).
So, I have to validate the received data.
Then, the received data:
cannot be empty;
must have 3 or more characters;
must have an header in the first two characters of the string data;
must have a "footer" in the last character of the string data;
must hava a valid CheckSum.
If the answer is valid, then I can handle the data. But before I'll have to extract this data from the response received.
Ok, this is a relatively easy task. Beforetime I would do it on a procedural way, using only one function and putting many if's.
Now I'm studying more about good programming practices, things seem to be getting harder to do.
To validate the device answer, is better create a class "ValidateReceivedData" for example and pass the received data in the constructor of this class? And then create a public method called "IsReceivedDataValid" that check all steps given above?
Or maybe would be better create a library with with several functions to validate the received data?
I'd like to use unit test too.
As I said before, I'm studying more to make better code. But I realize that I'm spending more time now to code than before. And there are too many questions that are arising, but in my view they seem easy to solve, but I'm not getting.
For what it's worth, I've done this sort of thing before using object-oriented design. Here's a high level possibility for your design:
ProtocolParser class:
Takes a SerialPort object, or equivalent, in the constructor and listens to it for incoming bytes
Passes received bytes to OnByteReceived, which implements the protocol-specific state machine (with states like Unknown, Stx1Received, Stx2Received, ..., CkSumReceived).
After an entire good message is received, creates an object of type Packet, which accepts a byte list in its constructor. It then raises an event PacketReceived, passing the Packet as an argument.
If a bad byte is received, it raises an event BadDataReceived and passes the bad data (for logging/debugging purposes, perhaps).
Packet class:
Takes a list/array of bytes and stores them as Command and Data properties.
Does not need to save the checksum, as this class is only meant to represent a valid packet.
The above classes are sufficient to implement the receive protocol. You should be able to test it by mocking a SerialPort class (i.e., the ProtocolParser could actually take an IDataSource instead of a SerialPort).
You could then add a higher-level class to implement your device-specific functions, which would listen to the PacketReceived event of the ProtocolParser.
Of course it will better to use OOP design.
By what you explained, I'd make at least 2 classes:
Message
Executer
The message will receive the command from the device, and the Executer will handle the message.
The Message object will initiate with the device's answer. It will parse it, and hold fields as you described:
STX
COMMAND
DATA
CHKSUM
ETX
Then an Executer object will receive the Message object and do the actual execution of the message, and hold the logical code.
I would go a step further than Yochai's answer, and create the following classes:
Command: Actually not a class, but an Enum value so you can check against Command.Read, etc., rather than just "knowing" what 0x01 and 0x02 mean.
Message: Just a plain object (POJO/POCO/whatever) that's intended to hold a data representation of the message. This would contain the following fields:
Command (the enum type mentioned earlier)
Data: List of the data. Depending on how the data is represented, you might create a class for this, or you could just represent each datum as a string.
MessageParser: this would have a function that would parse a string or text stream and create a Message object. If the text is invalid, I'd throw a customized exception (another class), which can be caught by the caller.
MessageExecutor: This would take a Message object and perform the action that it represents.
By making the intermediate representation object (Message), you make it possible to separate the various actions you're performing. For example, if the Powers That Be decide that the message text can be sent as XML or JSON, you can create different MessageParser classes without having to mess with the logic that decides what to do with the message.
This also makes unit testing far easier, because you can test the message parser independently of the executor. First test the message parser by calling the parse function and examining the resulting Message object. Then test the executor by creating a Message object and ensuring that the appropriate action is taken.