iPhone 网络编程:使用stream建立通讯
来源:互联网 发布:windows最长文件名 编辑:程序博客网 时间:2024/06/10 15:52
原文地址:http://www.devx.com/wireless/Article/43551/1954
Learn how to communicate with a server using TCP/IP and how to build a simple chat application.
In this article, you will learn how to communicate with a server using TCP/IP. You will also learn how to build a simple chat application using the concepts covered in one of my earlier articles.
For the sample project discussed in this article, you will use Xcode and create a new View-based Application project and name it as Network.
Using Streams for Network Communications
The easiest way to communicate over the network using sockets is to use the NSStream class. The NSStream class is an abstract class representing streams, where you can use it to read and write data. It can be used on memory, files, or networks. Using the NSStream class, you can communicate with a server simply by writing data to it and receive data from it by reading from an NSStream object.
On the Mac OS X, you can establish a connection to a server via the use of an NSHost and NSStream objects, like this:
NSInputStream *iStream;NSOutputStream *oStream;uint portNo = 500;NSURL *website = [NSURL URLWithString:urlStr];NSHost *host = [NSHost hostWithName:[website host]];[NSStream getStreamsToHost:hostport:portNoinputStream:&iStreamoutputStream:&oStream];
As you observed, the NSStream class has a class method named getStreamsToHost:port:inputStream:outputStream:, which creates an input stream and an output stream to a server where you can read and write data to it. However, the problem is that the getStreamsToHost:port:inputStream:outputStream:method is not supported on the iPhone OS. Hence, the above code will not work in your iPhone application.To resolve this problem, you can add a category to the existing NSStream class to replace the functionality provided by thegetStreamsToHost:port:inputStream:outputStream: method. To do so, right-click on the Classes group in Xcode and add a new file and name it asNSStreamAdditions.m. In the NSStreamAdditions.h file, add in the following:
#import @interface NSStream (MyAdditions)+ (void)getStreamsToHostNamed:(NSString *)hostNameport:(NSInteger)portinputStream:(NSInputStream **)inputStreamPtroutputStream:(NSOutputStream **)outputStreamPtr;@end
In the NSStreamAdditions.m file, add in the following (see Listing 1).The above code adds the class method named getStreamsToHostNamed:port:inputStream:outputStream: to the NSStream class. You can now use this method in your iPhone application to connect to a server using TCP.
Author's Note: The code for the category outlined here are based on Apple’s Technical Q&A1652.In the NetworkViewController.m file, insert the following statements in bold:
#import "NetworkViewController.h"#import "NSStreamAdditions.h"@implementation NetworkViewControllerNSMutableData *data;NSInputStream *iStream;NSOutputStream *oStream;
Define the connectToServerUsingStream:portNo: method so that you can connect to a server and then create an input and output stream objects:-(void) connectToServerUsingStream:(NSString *)urlStrportNo: (uint) portNo {if (![urlStr isEqualToString:@""]) {NSURL *website = [NSURL URLWithString:urlStr];if (!website) {NSLog(@"%@ is not a valid URL");return;} else {[NSStream getStreamsToHostNamed:urlStrport:portNoinputStream:&iStreamoutputStream:&oStream];[iStream retain];[oStream retain];[iStream setDelegate:self];[oStream setDelegate:self];[iStream scheduleInRunLoop:[NSRunLoop currentRunLoop]forMode:NSDefaultRunLoopMode];[oStream scheduleInRunLoop:[NSRunLoop currentRunLoop]forMode:NSDefaultRunLoopMode];[oStream open];[iStream open];}}}
You scheduled both the input and output streams to receive events on a run loop. Doing so prevents your code from blocking when there is no data available on the stream. The delegates for both stream objects are also set to self as you will implement the method for receiving data on the stream in this same class.Using CFNetwork for Network Communication
Another way to establish a connection to a server using TCP is through the CFNetwork framework. The CFNetwork is a framework in the Core Services Framework (C libraries), which provides abstractions for network protocols, such as HTTP, FTP, and BSD sockets.
To see how to use the various classes in the CFNetwork framework, add the following statements in bold to the NetworkViewController.m file:
#import "NetworkViewController.h"#import "NSStreamAdditions.h"#import @implementation NetworkViewControllerNSMutableData *data;NSInputStream *iStream;NSOutputStream *oStream;CFReadStreamRef readStream = NULL;CFWriteStreamRef writeStream = NULL;
Define the following connectToServerUsingCFStream:portNo: method as follows (see Listing 2).You first use the CFStreamCreatePairWithSocketToHost() method to create a readable and writable stream connected to a server via TCP/IP. This method returns a reference to a readable stream (readStream) and a writable stream (writeStream). They are then type-casted to their respective equivalent in Objective C -- NSInputStream and NSOutputStream. You then do the same as you did previously -- set their delegates as well as their run loop.
Sending Data
To send data to a server, you simply use the NSOutputStream object, like this:
-(void) writeToServer:(const uint8_t *) buf {[oStream write:buf maxLength:strlen((char*)buf)];}
The above method writes an array of unsigned integer bytes to the server.Reading Data
When data are received from the server, the stream:handleEvent: method will be fired. Hence, you will read all incoming data in this method. Implement this method as shown below:
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {switch(eventCode) {case NSStreamEventHasBytesAvailable:{if (data == nil) {data = [[NSMutableData alloc] init];}uint8_t buf[1024];unsigned int len = 0;len = [(NSInputStream *)stream read:buf maxLength:1024];if(len) {[data appendBytes:(const void *)buf length:len];int bytesRead;bytesRead += len;} else {NSLog(@"No data.");}NSString *str = [[NSString alloc] initWithData:dataencoding:NSUTF8StringEncoding];NSLog(str);UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"From server"message:strdelegate:selfcancelButtonTitle:@"OK"otherButtonTitles:nil];[alert show];[alert release];[str release];[data release];data = nil;} break;}}
This method contains two parameters -- an NSStream instance, and an NSStreamEvent constant. The NSStreamEvent constant can be one of the following:- NSStreamEventNone -- No event has occurred.
- NSStreamEventOpenCompleted -- The open has completed successfully.
- NSStreamEventHasBytesAvailable -- The stream has bytes to be read.
- NSStreamEventHasSpaceAvailable -- The stream can accept bytes for writing.
- NSStreamEventErrorOccurred -- An error has occurred on the stream.
- NSStreamEventEndEncountered -- The end of the stream has been reached.
The stream:handleEvent: method is also a good place to check for connection error. For example, if the connectToServerUsingStream:portNo: method fails to connect to the server, the error will be notified via the stream:handleEvent: method, with the NSStreamEvent constant set to NSStreamEventErrorOccurred.
Disconnecting
To disconnect from the server, define the disconnect method as shown below:
-(void) disconnect {[iStream close];[oStream close];}
Also, add in the following lines in bold to the dealloc method:- (void)dealloc {[self disconnect];[iStream release];[oStream release];if (readStream) CFRelease(readStream);if (writeStream) CFRelease(writeStream);[super dealloc];}
Testing the Application
You are now ready to put all the pieces together and test the code against a server. In the NetworkViewController.h file, declare the following outlet and action:
#import @interface NetworkViewController : UIViewController {IBOutlet UITextField *txtMessage;}@property (nonatomic, retain) UITextField *txtMessage;-(IBAction) btnSend: (id) sender;@end
Double-click on the NetworkViewController.xib file to edit it in Interface Builder. In the View window, populate it with the following views (see also Figure 1):- Text Field
- Round Rect Button
- Control-click on the File’s Owner item and drag and drop it over the Text Field view. Select txtMessage.
- Control-click on the Round Rect Button view and drag and drop it over the File’s Owner item. Select btnSend:.
Back in the NetworkViewController.m file, add the following lines of code in bold to the viewDidLoad method:
- (void)viewDidLoad {[self connectToServerUsingStream:@"192.168.1.102" portNo:500];//---OR---//[self connectToServerUsingCFStream:@"192.168.1.102" portNo:500];[super viewDidLoad];}
The above code assumes you are connecting to a server of IP address 192.168.1.102, at port 500. You will see how to write the server code shortly.Implement the btnSend: method as follows:
-(IBAction) btnSend: (id) sender {const uint8_t *str =(uint8_t *) [txtMessage.text cStringUsingEncoding:NSASCIIStringEncoding];[self writeToServer:str];txtMessage.text = @"";}
Release the txtMessage outlet in the dealloc method:- (void)dealloc {[txtMessage release];[self disconnect];[iStream release];[oStream release];if (readStream) CFRelease(readStream);if (writeStream) CFRelease(writeStream);[super dealloc];}
Building the Server
Up till this point, you have built a client on the iPhone that is ready to send some text over to a server. So what about the server? To test this application, I have built a very simple console server using C#. Here is the code for the Program.cs file (see Listing 3).
The server program performs the following:
- It assumes that the IP address of the server is 192.168.1.102. When testing on your end, replace this IP address with the IP address of your computer running this server application.
- It sends back to the client whatever data it receives.
- Once the data is received, the server no longer listens for incoming data. In order for the client to send data to it again, the client needs to reconnect to the server.
With the server code explained, you can now test your iPhone application. Type some text into the Text Field view and click the Send button. If the connection is established, you should see the Alert View displaying the data received.
A More Interesting Example
In one of my earlier articles for DevX.com, I wrote about how to build your own instant messenger application (see “Home-brew Your Own Instant Messenger App with Visual Studio .NET"> using .NET. In that article, I wrote about how to write a server and a client application to allow chat messages to be sent between multiple users. Using the code in that article, you could actually modify your iPhone application as a chat client and communicate with other users on other platforms.
Using the same project created earlier, add the following views to the View window (see also Figure 3):
- Label
- Text Field
- Round Rect Button
- Text View
In the NetworkViewController.h file, add the following statements in bold:
#import @interface NetworkViewController : UIViewController {IBOutlet UITextField *txtMessage;IBOutlet UITextField *txtNickName;IBOutlet UITextView *txtMessages;}@property (nonatomic, retain) UITextField *txtMessage;@property (nonatomic, retain) UITextField *txtNickName;@property (nonatomic, retain) UITextView *txtMessages;-(IBAction) btnSend:(id) sender;
Figure 5. Connections: Verify the connections.-(IBAction) btnLogin:(id) sender;@end
Perform the following actions:- Control-click on the File’s Owner item and drag and drop it over the top Text Field view. Select txtNickName.
- Control-click on the File’s Owner item and drag and drop it over the top Text View view. Select txtMessages.
- Control-click on the Round Rect Button view and drag and drop it over the File’s Owner item. Select btnLogin:.
Summary
In this article, you have seen how to communicate with another server using TCP/IP. Knowing how to communicate with the outside world allows you to build very interesting applications. In the next article, I will talk about Bluetooth programming on the iPhone.
- iPhone 网络编程:使用stream建立通讯
- Android--使用socket通讯建立网络聊天室1
- Android--使用socket通讯建立网络聊天室2
- C语言网络编程(二)建立套接字通讯UDP
- C语言网络编程(三)建立套接字通讯TCP
- iphone网络编程
- iphone 网络编程
- iphone网络编程总结
- iphone网络编程总结
- iphone 网络编程
- iphone 网络编程总结
- iPhone网络编程
- 网络编程总结 iphone
- iphone网络编程小结
- 【iPhone】网络编程
- iPhone开发技巧之网络篇(3)--- 使用NSOperation建立多任务网络连接
- 网络与通讯编程集锦
- windows网络编程通讯模型
- 线程
- 基于mini2440的按键驱动分析与总结
- 一个基于mini2440的测试按键与led灯的测试程序
- 在fedora15的环境下编译与安装opencv,并测试人脸检测程序
- iOS 证书与签名 解惑详解
- iPhone 网络编程:使用stream建立通讯
- hibernate几乎所有数据库配置
- windows电脑常识
- Linux实模式和保护模式
- 豆瓣的技术概要
- 随即生成无重复数字的数组(windows窗体)
- 以root身份进入fedora13的方法
- poj 1528 Perfection
- 平衡二叉树