Simplifying Assumptions.txt
上传用户:shqiling
上传日期:2009-10-04
资源大小:154k
文件大小:8k
源码类别:
MacOS编程
开发平台:
Objective-C
- Simplifying Assumptions
- =======================
- Networking is hard. To create a sufficiently simple sample, I had to make a number of simplifying assumptions. This document describes those assumptions and provide hints on how you would modify this sample code for production purposes.
- Code Structure
- --------------
- I structured the code to make it easy to understand, rather than to maximise maintainability and flexibility. Specifically:
- o The networking code (in some senses the 'model') is embedded directly in the controller code.
- o There's lots of redundant code in the controllers.
- In a real application you would probably separate the networking code out into a 'model' class that's used by each of the controllers. I didn't do this because I wanted folks to be able to get a good understanding of the overall structure by looking at just once source file.
- Security
- --------
- This sample pays no attention to security issues, which is totally unrealistic. Whenever you create production networking software you have to worry about security. There are many potential problems, including:
- o authentication -- Authentication is how you decide whose talking to you at the other end of the network connection. In many cases, but not always, authentication is tightly bound to authorisation (discussed next). Most people understand that a network server must authenticate its clients; it's less obvious that a network client should authenticate its server. Without this mutual authentication, you might leak sensitive user data to a spoofed server.
- o authorisation -- Authorisation is how you decide whether a particular entity is allowed to do some action. For example, a simple picture sharing server might allow all users to download and only some users to upload.
- A common practice for iPhone developers is to implement authentication and authorisation via pairing. The user must take some action to pair two computers, after which they can communicate without further user interaction.
- There is no direct support for pairing in the iPhone SDK, although you can use various APIs (like NSStream's TLS (see below) support and various Security framework APIs) to implement it yourself.
- o privacy -- You must assume that malicious users are looking at every piece of data you transfer over the network. If you ever transfer /any/ data that might be considered personal in the least way, you must ensure that this data is encrypted on the wire.
- In general I recommend that you err on the side of caution and consider all user data to be personal. This is because data that /you/ might not consider especially sensitive might be very sensitive in certain contexts. For example, if you're implementing a remote control application for a home media server, you might not consider the names of the tracks to be sensitive, but it's not hard to imagine a scenario where a user might.
- Your primary weapon for maintaining privacy is TLS (Transport Layer Security, aka SSL, or the Secure Sockets Layer). This is directly supported by NSStream, which makes it easy to add on-the-wire encryption to the code from this sample. The biggest problem, and the reason why this sample does not use TLS, is the issue of identity management. The Security framework provides some APIs for identity management, but they are not really sufficient for the type of peer-to-peer networking demonstrated by this sample.
- o malicious attack -- Whenever you communicate on the public Internet you open yourself up to malicious attack. In the worst-case scenario an attacker can craft a packet that causes your application to execute arbitrary code, at which point the attacker can take over the machine on which you're running and turn it into a zombie. You must carefully check all data that you receive from the network to prevent this.
- One specific form of malicious attack is denial of service. This sample makes no attempt to protect itself from denial of service attacks. For example, the server currently only supports a single connection and does not implement any timeouts on that connection, so an attacker could prevent any useful work from being done by simply opening a connection to the server and never closing it.
- Performance
- -----------
- This sample was designed for simplicity, not performance. If performance is a serious concern, you have some work to do. Some obvious things that are likely to improve performance include:
- o increasing the buffer size -- The code currently uses 32 KB buffers for both send and receive. That's probably way too small.
- o buffer allocation -- To simplify the code I allocate my transfer buffer as an instance variable (for sending) or on the stack (for receiving). That's less than ideal, especially as the buffer size gets larger. You should allocate the buffer on the heap.
- o file system I/O -- The code makes no attempt to optimise its use of the file system. For high-speed networking, especially on the Mac, the performance of file system I/O is as important as the performance of the network I/O. Also, you would want to overlap network and file system I/O to prevent bubbles in the network 'pipeline'.
- o threading -- The code currently uses NSStreams asynchronously on the main thread. You could probably reduce latency, and hence improve performance, by running the NSStreams on a separate thread.
- Before doing any of these things, make sure you actually measure where the performance bottlenecks are in your specific product.
- Service Discovery
- -----------------
- The code currently uses a hard-wired Bonjour service name. This is clearly bogus (for a start, it means you can only run one server on the network at any given time), but it does allow the sample to mostly ignore Bonjour and focus on NSStream.
- A production sample would either use Bonjour service discovery as illustrated by the WiTap sample code, or connect to a globally accessible server via its DNS name (you can create such streams using CFStreamCreatePairWithSocketToHost).
- <http://developer.apple.com/iphone/library/samplecode/WiTap/index.html#//apple_ref/doc/uid/DTS40007321>
- Multiple Connections
- --------------------
- To keep things simple the server components of this sample only support a single connection at any given time. This is likely to be insufficient for your needs. A real server would typically have some sort of connection object that's instantiated to run a specific connection. For an example of this, see the HTTPServer and HTTPConnection classes in the CocoaHTTPServer sample.
- <http://developer.apple.com/samplecode/CocoaHTTPServer/index.html>
- Reliability
- -----------
- The sample is reliable within the bounds set by its design. However, many of those bounds are only appropriate for sample code, not for production code that is to be widely deployed. Specifically:
- o The protocol used by this sample is trivial. To send a file, we connect and send data until all of the data is sent. To receive a file, we connect and then receive data until we get an end-of-file. This is not appropriate for production code because there's no way to verify that all of the data has been received. Production code would need to implement some protocol over raw TCP to convey that information. For example, you could prepend a simple header that includes metadata about the file being transferred.
- o TCP is supposed to deliver data reliably. However, that does not always happen (especially in a world of middleboxes). Production code should use some sort of end-to-end checksum to ensure that the data has arrived intact.
- o The sample makes no attempt to warn the user when networking is impossible, something that iPhone OS applications are expected to do. For example, if the device is in Airplane mode, off-device networking is impossible and you should probably tell the user that.
- IPv6
- ----
- iPhone OS does not current support IPv6, so it was not a major concern for this sample. Nevertheless, the client components should work with IPv6 without modification. The server components, however, would require minor changes to work with IPv6. Again, the CocoaHTTPServer sample shows how this is done.