纯IOS代码套接字连接

转自:http://hi.baidu.com/duan2834/item/5b9f877e1ce298580d0a07d6

使用CFNetwork框架

  使用 TCP协议建立到服务器的连接,还有一种办法是使用CFNetwork框架,CFNetwork是核心服务框架(C库)中的一个框架,它为网络协议提供了抽象,如HTTP,FTP和BSD套接字。

  为了弄清楚如何使用CFNetwork框架中的各种类,在 NetworkViewController.m文件中增加下面的代码:

1 #import "NetworkViewController.h"
2 #import "NSStreamAdditions.h"
3 #import
4 @implementation NetworkViewController
5 NSMutableData *data;
6 NSInputStream *iStream;
7 NSOutputStream *oStream;
8 CFReadStreamRef readStream = NULL;
9 CFWriteStreamRef writeStream = NULL;
10

   然后使用下面的代码定义connectToServerUsingCFStream:portNo::

1 -(void) connectToServerUsingCFStream:(NSString *) urlStr portNo: (uint) portNo {
2         CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
3                                        (CFStringRef) urlStr,
4                                        portNo,
5                                        &readStream,
6                                        &writeStream);
7     if (readStream && writeStream) {
8         CFReadStreamSetProperty(readStream,
9                                 kCFStreamPropertyShouldCloseNativeSocket,
10                                 kCFBooleanTrue);
11         CFWriteStreamSetProperty(writeStream,
12                                 kCFStreamPropertyShouldCloseNativeSocket,
13                                 kCFBooleanTrue);
14         iStream = (NSInputStream *)readStream;
15         [iStream retain];
16         [iStream setDelegate:self];
17         [iStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
18             forMode:NSDefaultRunLoopMode];
19         [iStream open];
20         oStream = (NSOutputStream *)writeStream;
21         [oStream retain];
22         [oStream setDelegate:self];
23         [oStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
24             forMode:NSDefaultRunLoopMode];
25         [oStream open];        
26     }
27 }
28

  你第一次使用CFStreamCreatePairWithSocketToHost()方法创建一个可读写的流,通过TCP/IP连接到服务器,这个方法返回这个可读写流(readStream和writeStream)的引用,它们和Objective C中的NSInputStream和NSOutputStream是等效的。

  发送数据

  使用 NSOutputStream对象向服务器发送数据,如:

  1 -(void) writeToServer:(const uint8_t *) buf {

  2 [oStream write:buf maxLength:strlen((char*)buf)];

  3 }

  4

  这个方法向服务器发送一 组无符号整数字节。

  读取数据

  从服务器接收数据时,将会触发stream:handleEvent:方法,因此可以使用这个方法接收所有入站数据,这个方法实现如下:

1 (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
2      switch(eventCode) {
3         case NSStreamEventHasBytesAvailable:
4         {
5             if (data == nil) {
6                 data = [[NSMutableData alloc] init];
7             }
8             uint8_t buf[1024];
9             unsigned int len = 0;
10             len = [(NSInputStream *)stream read:buf maxLength:1024];
11             if(len) {    
12                 [data appendBytes:(const void *)buf length:len];
13                 int bytesRead;
14                 bytesRead += len;
15             } else {
16                 NSLog(@"No data.");
17             }
18             NSString *str = [[NSString alloc] initWithData:data
19                                 encoding:NSUTF8StringEncoding];
20             NSLog(str);
21             UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"From server" 
22                                                             message:str
23                                                            delegate:self
24                                                   cancelButtonTitle:@"OK" 
25                                                   otherButtonTitles:nil];
26             [alert show];
27             [alert release];
28             [str release];
29             [data release];        
30             data = nil;
31         } break;
32     }
33 }
34

  这个方法包括两个参数:一个是NSStream实例,一个是NSStreamEvent常量,NSStreamEvent常量可以是以下的值:

   NSStreamEventNone:无事件发生。

  NSStreamEventOpenCompleted:打开事件已经成功完成。

   NSStreamEventHasBytesAvailable:已经读取的流字节数。

   NSStreamEventHasSpaceAvailable:流接收的可写入的字节数。

   NSStreamEventErrorOccurred:在流上发生了错误。

   NSStreamEventEndEncountered:已经抵达流的结尾。

  读取入站数据时,你应该检查 NSStreamEventHasBytesAvailable常量,在这个方法中,你可以读取入站数据流,然后UIAlertView对象显示接收到的数据。

  stream:handleEvent:方法也是检查连接错误的一个好方法,例如,如果 connectToServerUsingStream:portNo:方法连接到服务器时失败了,错误将使用stream:handleEvent:方法通知,NSStreamEvent常量设置为NSStreamEventErrorOccurred。

  断开连接

   为了断开与服务器的连接,定义如下的断开方法:

  -(void) disconnect {

  [iStream close];

  [oStream close];

  }

  然后将下面的代码添加到dealloc分发 中:

  - (void)dealloc {

  [self disconnect];

  [iStream release];

  [oStream release];

  if (readStream) CFRelease(readStream);

  if (writeStream) CFRelease(writeStream);

   [super dealloc];

  }

  测试应用程序

  现在可以将所有代码集合到一起进行测试了,在NetworkViewController.h文件中,声明下面的出口和行为:

  #import

   @interface NetworkViewController : UIViewController {

  IBOutlet UITextField *txtMessage;

  }

  @property (nonatomic, retain) UITextField *txtMessage;

  -(IBAction) btnSend: (id) sender;

   @end

  双击NetworkViewController.xib,在Interface Builder中打开编辑它,在View窗口中,使用下面的视图填充它,如图1所示。

  l 文本区域(Text Field)

   l 圆形按钮(Round Rect Button)

  纯IOS代码套接字连接_第1张图片

  图 1 填充:使用视图填充View窗口

  执行下面的操作

  1、在File’s Owner上点击,将其拖到文本区域视图中,选择txtMessage。

  2、选中圆形按钮视图,将其拖到File’s Owner上,选择btnSend。

  在File’s Owner上点击右键,验证它的连接,如图2所示。

  纯IOS代码套接字连接_第2张图片

  图 2 验证:验证File’s Owner上的连接

  回到NetworkViewController.m文件,将下面的代码添加到 viewDidLoad方法中。

  - (void)viewDidLoad {

  [self connectToServerUsingStream:@"192.168.1.102" portNo:500];

   //---OR---

  //[self connectToServerUsingCFStream:@"192.168.1.102" portNo:500];

  [super viewDidLoad];

  }

  上面的代码假设你正连接到一个ip地址为192.168.1.102的服务器的500端口上。btnSend:方法的代码如下:

  -(IBAction) btnSend: (id) sender {

  const uint8_t *str =

  (uint8_t *) [txtMessage.text cStringUsingEncoding:NSASCIIStringEncoding];

   [self writeToServer:str];

  txtMessage.text = @"";

  }

   在dealloc方法中重新发布txtMessage出口。

  - (void)dealloc {

   [txtMessage release];

  [self disconnect];

  [iStream release];

  [oStream release];

  if (readStream) CFRelease(readStream);

  if (writeStream) CFRelease(writeStream);

   [super dealloc];

  }

  构建服务器

  现在已经构建好一个可以在iPhone上运行的客户端,并已经可以通过它向服务器发送一些文本信息,但为了测试这个应用程序还需要一个服务端程序,我使用C#构建了一个非常简单的控制台服务器,下面是 Program.cs文件的代码。

1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Net.Sockets;
5 namespace Server_CS
6 {
7     class Program
8     {
9         const int portNo = 500;
10         static void Main(string[] args)
11         {
12             System.Net.IPAddress localAdd = 
13                 System.Net.IPAddress.Parse("192.168.1.102");
14             TcpListener listener = new TcpListener(localAdd, portNo);
15             listener.Start();
16             while (true)
17             {
18                 TcpClient tcpClient = listener.AcceptTcpClient();
19                 NetworkStream ns = tcpClient.GetStream();
20                 byte[] data = new byte[tcpClient.ReceiveBufferSize];
21                 int numBytesRead = ns.Read(data, 0,
22                     System.Convert.ToInt32(tcpClient.ReceiveBufferSize));
23                 Console.WriteLine("Received :" + 
24                     Encoding.ASCII.GetString(data, 0, numBytesRead));
25                 //---write back to the client---
26                 ns.Write(data, 0, numBytesRead);
27             }
28         }
29     }
30 }
31

  服务端程序执行下面的任 务:

  l 它假设服务器的ip地址是192.168.1.102,在你的终端上测试时,请将这个ip地址替换为你运行这个服务端程序的计算机的ip地址。

   l 它将接收到的所有数据返回给客户端。

  l 一旦接收到数据,服务端不再监听入站数据,如果客户端要再次发生数据,需要重新连接到服务器。

  在文本区域中输入一些文字,然后点击 Send按钮,如果连接成功,你将会看到Alert视图显示接收到数据。


你可能感兴趣的:(纯IOS代码套接字连接)