zoukankan      html  css  js  c++  java
  • iOS-----使用CFNetwork实现TCP协议的通信

    使用CFNetwork实现TCP协议的通信   

    TCP/IP通信协议是一种可靠的网络协议,它在通信的两端各建立一个通信接口,从而在通信的两端之间形成网络虚拟链路.一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信.CFNetwork对基于TCP协议的网络通信提供了良好的封装,CFNetwork使用CFSocket来代表两端的通信接口,还可以通过CFStream读/写数据.

    IP地址与端口号

    IP地址用于唯一地标识网络中的一个通信实体,这个通信实体既可以是一台主机,也可以是一台打印机,或者是路由器的某一个端口.在基于IP协议的网络中传输的数据包,都必须使用IP地址来进行标识.

       IP地址是数字型的,是一个32位(32Bit)整数,通常把它分成4个8位的二进制数,每8为之间用圆点隔开,每个8位整数可以转换成一个0-255的十进制整数,因此看到的IP地址常常是这样的形式:198.162.8.10.

       NIC(Internet Network Information Center)统一负责全球Internet IP地址的规划、管理,而Inter NIC、APNIC、RIPE三大网络信息中心具体负责美国及其他地区的IP地址分配。其中APNIC负责亚太地区的IP管理,我国申请IP地址也要通过APNIC,APNIC的总部设在日本东京大学。

      IP地址被分成了A、B、C、D、E五类,每个类别的网络标识和主机标识各有规则。

    1. A类:10.0.0.0~10.255.255.255
    2. B类:172.16.0.0~172.31.255.255
    3. C类:192.168.0.0~192.168.255.255

    IP地址用于唯一地标识网络上的一个通信实体,但一个通信实体可以有多个通信程序同时提供网络服务,此时还需要使用端口.

    端口是一个16位的整数,用于标识数据交给那个通信程序处理.因此,端口就是应用程序与外界交流的出入口,它是一种抽象的软件结构,包括一些数据结构和I/O(基本输入/输出)缓冲区.

    不同的应用程序处理不同端口上的数据,同一台机器上不能有两个程序使用同一个端口,端口号可以从0到65535,通常将它分为3类.

    1. 公认端口(Well Know Ports):从0到1023,它们紧密绑定(Binding)一些特定的服务.
    2. 注册端口(Registered Ports):从1024到49151,它们松散地绑定一些服务。应用程序通常使用这个范围内的端口。
    3. 动态和/或私有端口(Dynamic and/or Private Ports):从49152到65535,这些端口是应用程序使用的动态端口,应用程序一般不会主动使用这些端口。      

    TCP协议基础

    IP协议是 Internet 上使用的一个关键协议,它是全称是 Internet Protocol, 即Internet协议,通常简称 IP 协议.通过使用 IP协议,使 Internet 成为一个允许连接不同类型的计算机和不同操作系统的网络.

    要使两台计算机之间彼此进行通信,必须使两台计算机使用同一种”语言”,IP 协议只保证计算机能发送和接收分组数据. IP协议负责将消息从一个主机传送到另一个主机,消息在传送的过程中被分割成一个个小包.

    安装 IP 协议之后,可保证计算机之间发送和接收数据,但 IP协议还不能解决数据分组在传输过程中可能出现的问题.因此,若要解决可能出现的问题,连接上 Internet 的计算机还需要安装 TCP 协议来提供可靠并且无差错的通信服务.

    TCP协议被称作一种端对端协议.这是因为它为两台计算机之间的连接起到了重要作用-----当一台计算机需要与另一台远程计算机连接时, TCP 协议会让它们建立一个连接:用于发送和接收数据的虚拟链路.

    TCP 协议负责收集这些信息包,并将其按适当的次序放好传送,在接收端收到后再将其正确地还原. TCP协议保证了数据包在传送中准备无误. TCP 协议使用重发机制:当一个通信实体发送一个消息给另一个通信实体后,需要收到另一个通信实体的确认信息,如果没有收到另一个通信实体的确认信息,则会再次重发刚才发送的信息.

    通过这种重发机制, TCP协议向应用程序提供可靠的通信连接,使它能够自动适应网上的各种变化.即使在 Internet 暂时出现堵塞的情况下, TCP也能够保证通信的可靠性.

    使用 CFSocket 实现 TCP服务器端

    使用CFSocket建立服务器的步骤如下.

    1

    创建一个监听Socket Accept(Socket连接)的CFSocket,并为kCFSocketAcceptCallBack事件绑定回调函数.

    2

    调用CFSocketSetAddress()函数,将服务器端的CFSocket绑定到本地IP地址和端口

    3

    将CFSocket作为source添加到指定线程的CFRunLoop上,并运行该线程的CFRunLoop,从而保证该CFSocket能持续不断地接受来自客户端的连接.

    代码片段

      1 #import <sys/socket.h>
      2 
      3 #import <arpa/inet.h>
      4 
      5 #import<Foundation/Foundation.h>
      6 
      7 // 读取数据的回调函数
      8 
      9 void readStream(CFReadStreamRef  iStream, CFStreamEventType eventType, void *clientCallBackInfo)
     10 
     11 {
     12 
     13   UInt 8 buff[2048];
     14 
     15   CFIndex hasRead = CFReadStreamRead(iStream, buff, 2048);
     16 
     17   if(hasRead > 0)
     18 
     19   {
     20 
     21 // 强制只处理hasRead前面的数据
     22 
     23 buff[hasRead]=’0’;
     24 
     25 printf(“接收到数据: %s
    ”, buff);
     26 
     27 }
     28 
     29 }
     30 
     31 // 有客户端连接进来的回调函数
     32 
     33 void TCPServerAcceptCallBack(CFSocketRef  socket, CFSocketCallBackType type, CFDataRef  address, const void *data, void *info )
     34 
     35 {
     36 
     37   // 如果有客户端Socket连接进来
     38 
     39   if(kCFSocketAcceptCallBack == type)
     40 
     41   {
     42 
     43 // 获取本地Socket的Handle
     44 
     45 CFSocketNativeHandle  nativeSocketHandle = *(CFSocketNativeHandle*)data;
     46 
     47 uint8_t name[SOCk_MAXADDRLEN];
     48 
     49 socklen_t  nameLen = sizeof(name);
     50 
     51 // 获取对方Socket信息,还有getsocketname()函数则用于获取本程序所在Socket信息
     52 
     53 if(getpeername(nativeSocketHandle, (struct sockaddr *)name, &nameLen) != 0)
     54 
     55 {
     56 
     57   NSLog(@”error”);
     58 
     59   exit(1);
     60 
     61 }
     62 
     63 // 获取连接信息
     64 
     65 struct sockeaddr_in * addr_in = (struct socketaddr_in*) name;
     66 
     67 NSLog(@”%s: %d 连接进来了”,  inet_ntoa(addr_in->sin_addr)
     68 
     69 ,  addr_in->sin_port);
     70 
     71 CFReadStreamRef  iStream;
     72 
     73 CFWriteStreamRef  oStream;
     74 
     75 // 创建一组可读/写的CFStream
     76 
     77 CFStreamCreatePairWithSocket(kCFAllocatorDefault , nativeSocketHandle, &iStream, &oStream);
     78 
     79 if(iStream && oStream)
     80 
     81 {
     82 
     83    // 打开输入流和输入流
     84 
     85    CFReadStreamOpen(iStream);
     86 
     87    CFWriteStreamOpen(oStream);
     88 
     89    CFStreamClientContext streamContext = {0, NULL, NULL, NULL};
     90 
     91    if(!CFReadStreamSetClient(iStream, kCFStreamEventHasBytesAvailable,
     92 
     93 readStream/*回调函数,当有可读的数据时调用*/, &streamContext))
     94 
     95 {
     96 
     97 exit(1);
     98 
     99 }
    100 
    101 CFReadStreamScheduleWithRunLoop(iStream,  CFRunLoopGetCurrent(),
    102 
    103 kC FRunLoopCommonModes);
    104 
    105 const char* str = “您好,您收到Mac服务器的新年祝福!
    ”;
    106 
    107 // 向客户端输出数据
    108 
    109 CFWriteStreamWrite(oStream, (UInt8 *)str, strlen(str) + 1);
    110 
    111 }
    112 
    113 }
    114 
    115 }
    116 
    117 int main(int argc, char * argv[])
    118 
    119 {
    120 
    121   @autoreleasepool{
    122 
    123    // 创建Socket,指定TCPServerAcceptCallBack
    124 
    125    // 作为kCFSocketAcceptCallBack事件的监听函数
    126 
    127    CFSocketRef _socket = CFSocketCreate(kCFAllocatorDefault
    128 
    129 , PF_INEF // 指定协议族,如果该参数为0或者负数,则默认为PF_INEF
    130 
    131 // 指定Socket类型,如果协议族为PF_INEF,且该参数为0或负数
    132 
    133   // 则它会默认为SOCK_STREAM,如果要使用UDP协议,则该参数指定为SOCK_DGRAM
    134 
    135 , SOCK_STREAM
    136 
    137  // 指定通信协议。如果前一个参数为SOCK_STREAM,则默认使用TCP协议
    138 
    139  // 如果前一个参数为SOCK_DGRAM,则默认使用UDP协议
    140 
    141 ,IPPROTO_TCP
    142 
    143 // 该参数指定下一个回调函数所监听的事件类型
    144 
    145   ,kCFSocketAcceptCallBack
    146 
    147   ,TCPServerAcceptCallBack // 回调函数
    148 
    149   ,NULL);
    150 
    151  if(_socket == NULL)
    152 
    153  {
    154 
    155    NSLog(@”创建Socket失败!”);
    156 
    157    return 0;
    158 
    159 }
    160 
    161 int optval = 1;
    162 
    163 // 设置允许重用本地地址和端口
    164 
    165 setsockopt(CFSocketGetNative(_socket), SOL_SOCKET,  SO_REUSEADDR,
    166 
    167 (void *)&optval, sizeof(optval));
    168 
    169 // 定义sockaddr_in类型的变量,该变量将作为CFSocket的地址
    170 
    171 struct sockaddr_in addr4;
    172 
    173 memset(&addr4, 0 , sizeof(addr4));
    174 
    175 addr4.sin_len = sizeof(addr4);
    176 
    177 addr4.sin_family = AF_INEF;
    178 
    179 //  设置该服务器监听本机任意可用的IP地址
    180 
    181 // addr4.sin_addr.s_addr =htonl(INADDR_ANY);
    182 
    183 // 设置服务器监听地址
    184 
    185 addr4.sin_addr.s_addr = inet_addr(“192.168.1.100”);
    186 
    187 // 设置服务器监听端口
    188 
    189 addr4.sin_port = htons(30000);
    190 
    191 // 将IPv4的地址转换成CFDataRef
    192 
    193 CFDataRef address = CFDataCreate(kCFAllocatorDefault
    194 
    195  , (UInt8 *)&addr4, sizeof(addr4));
    196 
    197 //  将CFSocket绑定到指定IP地址
    198 
    199 if(CFSocketSetAddress(_socket, address) != kCFSocketSuccess)
    200 
    201 {
    202 
    203    NSLog(@”地址绑定失败!”);
    204 
    205    // 如果_socket不为NULL,则释放_socket
    206 
    207   if(_socket)
    208 
    209   {
    210 
    211     CFRelease(_socket);
    212 
    213     exit(1);
    214 
    215 }
    216 
    217 _socket = NULL;
    218 
    219 }
    220 
    221   NSLog(@”---启动循环监听客户端连接-----”);
    222 
    223   // 获取当前线程的CFRunLoop
    224 
    225 CFRunLoopRef  cfRunLoop = CFRunLoopGetCurrent();
    226 
    227 // 将_socket包装成CFRunLoopSource
    228 
    229 CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(
    230 
    231 kCFAllocatorDefault , _socket, 0);
    232 
    233 // 为CFRunLoop对象添加source
    234 
    235 CFRunLoopAddSource(cfRunLoop,  source,  kCFRunLoopCommonModes);
    236 
    237 CFRelease(source);
    238 
    239 //  运行当前线程的CFRunLoop
    240 
    241 CFRunLoopRun();
    242 
    243 }
    244 
    245   return 0;
    246 
    247 }

    说明

       上面程序中的main()函数作为程序的入口,程序从该函数开始执行.main()函数的第1段红色字代码创建了一个CFSocket对象,并指定了该CFSocket使用TCP协议,基于流经行输入/输出.

    sockaddr_in类型的结构体变量,该结构体变量将会作为CFSocket绑定的监听地址,因此程序为socketaddr_in类型的结构体变量指定了IP地址和端口,然后程序中的红色字代码调用了CFSocketSetAddress()函数将指定CFSocket绑定到指定的IP地址和端口.

    main()函数的最后一段红色体代码将该CFSocket作为source添加到主线程的CFRunLoop上,并运行主线程的CFRunLoop,从而保证该CFSocket能持续不断地接受来自客户端的连接.

     

      该程序的另一个重点是TCPServerAcceptCallBack回调函数---当CFSocket接受来自客户端的连接后,该函数将会被调用.该函数主要做了如下4件事情.

    1

    调用getpeername()函数获取远程Socket的相关信息,从而在控制台打印出来连接进来的客户端IP地址和端口.

    2

    调用CFStreamCreatePairWithSocket()函数通过CFSocket获取CFReadStreamRef、CFWriterStreamRef,接下来程序即可通过这两个流进行读/写网络数据。

    3

    再次使用主线程的CFRunLoop监听来自客户端的数据。

    4

    向客户端写入一段字符串。

    使用CFSocket实现TCP客户端

    创建TCP客户端同样通过CFSocket完成。使用CFSocket创建Socket客户端的步骤如下。

    1

    创建一个不监听任何事件或监听Connection的CFSocket。如果要监听Connection,则需要为kCFSocketConnectCallBack事件绑定回调函数.

    2

    调用CFSocketConnectToAddress()函数,将客户端的CFSocket连接到指定IP地址和端口的服务器上.

    3

    得到客户端CFSocket之后,既可直接使用CFSocket对应的CFSocketNativeHandle进行读/写,也可通过CFSocket获取CFReadStreamRef、CFWriteStreamRef后进行读/写。

    代码片段

    ViewController.m
    
    #import <sys/socket.h>
    
    #import <netinet/in.h>
    
    #import <arpa/inet.h>
    
    #import <ViewController.h>
    
     
    
    @implementation ViewController
    
    CFSocketRef  _socket;
    
    BOOL isOnline;
    
    - (void)viewDidLoad
    
    {
    
       [super viewDidLoad];
    
       // 创建Socket,无须回调函数
    
       _socket = CFSocketCreate(kCFAllocatorDefault,
    
    PF_INEF // 指定协议族,如果该参数为0或者负数,则默认为PF_INET
    
    // 指定Socket类型,如果协议族为PF_INEF,且该参数为0或负数
    
    // 则它会默认为SOCK_STREAM,如果要使用UDP协议,则该参数指定为SOCK_DGRAM
    
    , SOCK_STREAM
    
    // 指定通信协议.如果前一个参数为SOCK_STREAM,则默认使用TCP协议
    
    // 如果前一个参数SOCK_DGRAM,则默认使用UDP协议
    
    , IPPROTO_TCP
    
    // 该参数指定下一个回调函数所监听的事件类型
    
    ,  kCFSocketNoCallBack
    
    ,  nil
    
    ,  NULL);
    
    if(_socket != nil)
    
    {
    
      // 定义sockaddr_in类型的变量,该变量将作为CFSocket的地址
    
      struct  sockaddr_in  addr4;
    
      memset(&addr4, 0, sizeof(addr4));
    
      addr4.sin_len = sizeof(addr4);
    
      addr4.sin_family = AF_INET;
    
      // 设置连接远程服务器的地址
    
      addr4.sin_addr.s_addr = inet_addr(“192.168.1.88”);
    
      // 设置连接远程服务器的监听端口
    
      addr4.sin_port = htons(30000);
    
      // 将IPv4的地址转换为CFDataRef
    
      CFDateRef addres = CFDataCreate(kCFAllocatorDefault
    
    ,  (UInt8 *)&addr4, sizeof(addr4));
    
    // 连接远程服务器的Socket,并返回连接结果
    
    CFSocketError  result = CFSocketConnectionToAddress(_socket
    
    ,  address // 指定远程服务器的IP地址和端口
    
    ,  5 // 指定连接超时时长, 如果该参数为负数, 则把连接操作放在后台进行
    
    //  当_socket消息类型为kCFSocketConnectCallBack时
    
    //  将会在连接成功或失败的时候在后台触发回调函数
    
    );
    
    // 如果连接远程服务器成功
    
    if(result == kCFSocketSuccess)
    
    {
    
      isOnline = YES;
    
    // 启动新线程来读取服务器响应的数据
    
    [NSThread detachNewThreadSelector:@selector(readStream)
    
    toTarget:self withObject:nil];
    
    }
    
    }
    
    }
    
    // 读取接收的数据
    
    - (void)readStream
    
    {
    
       char buffer[2048];
    
       int hasRead;
    
       // 与本机关联的Socket如果已经失效,则返回-1:INVALID_SOCKET
    
       while ((hasRead = recv(CFSocketGetNative(_socket)
    
    , buffer, sizeof(buffer), 0)))
    
    {
    
       NSLog(@”%@”,[[NSString alloc] initWithBytes:buffer
    
    length:hasRead encoding:NSUTF8StringEncoding]);
    
    }
    
    }
    
    -  (IBAction)clicked:(id)sender
    
    {
    
      if(isOnline)
    
      {
    
    NSString* stringTosend = @”来自iOS客户端的问候”;
    
    const char* data = [stringTosend UTF8String];
    
    send(CFSocketGetNative(_socket), data, strlen(data) +1, 1);
    
    }
    
    else
    
    {
    
      NSLog(@”暂未连接服务器”);
    
    }
    
    }
    
    @end

    说明

       上面程序中的第1段红色字代码创建了一个CFSocket, 该CFSocket同样适用了TCP协议,并且是基于SOCK_STREAM流的Socket,然后程序创建了一个struct  sockaddr_in 结构体变量,该结构体变量代表远程服务器的地址.

       上面程序中的第2段红色字代码调用了CFSocketConnectToAddress()函数将CFSocket连接到远程服务器地址---如果连城成功,就可得到一个进行网络读/写的CFSocket.剩下的事情是程序以readStream作为新线程的执行体,启动了一个新线程,其中readStream方法中的红色字代码调用了recv()函数从指定CFSocket读取数据.而clicked:方法则用于向服务器发送数据,该方法中的红色字代码调用了send()函数向CFSocket发送数据.

    使用CocoaAsyncSocket实现TCP客户端

       CocoaAsyncSocket封装了CFNetwork底层的CFSocket和CFStream,并提供了异步操作,从而可简化Socket网络编程.CocoaAsyncSocket不仅支持TCP协议的网络编程,也支持UDP协议的网络编程.CocoaAsyncSocket是CFSocket的绝佳替代者.

    CocoaAsyncSocket主要有以下特性

    1

    非阻塞方式的读和写,而且可设置超时时长.

    2

    自动的Socket接收。如果调用它接受连接,它将为每个连接启动新的实例,当然也可以立即关闭这些连接。

    3

    委托(delegate)支持。错误、连接、接收、完整的读取、完整的写入、进度以及断开连接,都可通过委托模式调用。

    4

    所有操作都封装在一个类中,无须操作Socket或流,该类封装了所有操作。

    下载和安装CocoaAsyncSocket的步骤如下

    1.CocoaAsyncSocket的官方网站是https://github.com/robbiehanson/CocoaAsyncSocket,登录该站点,单击页面中间的release链接.

    2.浏览器将会打开一个新的列表页面,该列表页面中列出了CocoaAsyncSocket的所有发布版本,建议下载最新版的CocoaAsyncSocket.

    3.下载完成将可以得到一个CocoaAsyncSocket.zip文件,解压该压缩包,将可以看到如下文件结构.

            RunLoop:该目录下包含了AsyncSocketAsyncUDPSocket两个类的源文件和Xcode目录.其中AsyncSocket就是基于TCP协议的CocoaAsyncSocket实现,AsyncUDPSocket就是基于UDP协议的AsyncUDPSocket实现。而Xcode目录下则包含了使用CocoaAsyncSocket开发服务器端与客户端的示例项目。

            GCD:该目录下的内容与RunLoop目录下的内容基本相似,只是类名变成了GCDAsyncSocket、GCDAsyncUDPSocket,这是因为该目录下的CocoaAsyncSocket是基于GCD的实现。

            Vendor:其他相关类。

            其他杂项文件。

            需要为项目增加CFNetwork.framework框架。

    添加CocoaAsyncSocket支持之后,使用AsyncSocket开发TCP客户端的步骤如下

    1. 创建一个AsyncSocket对象,创建该对象时需要指定该AsyncSocket的delegate,该delegate必须实现AsyncSocketDelegate协议,该delegate对象负责处理AsyncSocket在网络通信过程中的各种事件。
    2. 调用AsyncSocket对象的connectToHost:onPort:error:方法控制AsyncSocket对象连接指定IP地址、指定端口的服务器程序,该方法的最后一个参数用于接收连接错误。
    3. 为AsyncSocket的delegate对象(实现AsyncSocketDelegate协议的对象)实现特定的方法,该delegate负责处理AsyncSocket在网络通信过程中的各种事件。
    4. 如果需要发送数据,则调用AsyncSocket的writeData:withTimeout:tag:方法;如果需要读取数据,则调用AsyncSocket的readDataWithTimeout:tag:方法。当数据发送完成或数据读取完成时,都会激发AsyncSocket的delegate对象的特定方法。

    代 码 片 段

      1 ViewController.h
      2 
      3 #import <UIKit/UIKit.h>
      4 
      5 #import “AsyncSocket.h”
      6 
      7 @interface ViewController : UIViewController<AsyncSocketDelegate>
      8 
      9 @property (strong, nonatomic) IBOutlet UITextView *showView;
     10 
     11 @property (strong, nonatomic) IBOutlet UITextFiled *inputField;
     12 
     13 - (IBAction)finishEdit:(id)sender;
     14 
     15 - (IBAction)send:(id)sender;
     16 
     17 @end
     18 
     19 ViewController.m
     20 
     21 @implementation ViewController
     22 
     23 NSString* myName;
     24 
     25 AsyncSocket* socket;
     26 
     27 BOOL iSOnline;
     28 
     29 - (void)viewDidLoad
     30 
     31 {
     32 
     33   [super viewDidLoad];
     34 
     35   // 创建一个UIAlertView提醒用户输入名字
     36 
     37   UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@”名字”
     38 
     39 message:@”请输入您的名字”  delegate:self
     40 
     41 cancelButtonTitle:@”确定” otherButtonTitles: nil ];
     42 
     43 // 设置该UIAlertView为UIAlertViewStylePlainTextInput风格
     44 
     45 alert.alertViewStyle = UIAlertViewStylePlainTextInput;
     46 
     47 [alert show];
     48 
     49 }
     50 
     51 - (IBAction)finishEdit:(id)sender
     52 
     53 {
     54 
     55    [sender resignFirstResponder];
     56 
     57 }
     58 
     59 - (IBAction)send:(id)sender
     60 
     61 {
     62 
     63   if(isOnline)
     64 
     65   {
     66 
     67 // 定义要发送的字符串内容
     68 
     69 NSString* stringTosend = [NSString stringWithFormat:@”%@说: %@”, myName, self.inputField.text];
     70 
     71 self.inputField.text = nil;
     72 
     73 NSData *data = [stringTosend dataUsingEncoding:NSUTF8StringEncoding];
     74 
     75 // 调用writeData:withTimeout:tag:方法发送数据
     76 
     77 [socket  writeData:data  withTimeout: - 1  tag:0];
     78 
     79   }
     80 
     81   else
     82 
     83   {
     84 
     85     NSLog(@”暂未连接服务器”);
     86 
     87 }
     88 
     89 }
     90 
     91 // AsyncSocketDelegate中定义的方法,当成功连接到服务器时激发该方法
     92 
     93 - (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
     94 
     95 {
     96 
     97   isOnline = YES;
     98 
     99   // 调用readDataWithTimeout: tag: 方法读取数据
    100 
    101  [sock readDataWithTimeout:-1 tag:0];
    102 
    103 }
    104 
    105 // AsyncSocketDelegate中定义的方法,当读取数据完成时激发该方法
    106 
    107 - (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
    108 
    109 {
    110 
    111   // 获取读到的内容
    112 
    113   NSData* strData = [data subDataWithRange:NSMakeRange(0, [data length])];
    114 
    115   NSString* content = [[NSString alloc] initWithData:strData encoding:NSUTF8StringEncoding];
    116 
    117   if(content)
    118 
    119   {
    120 
    121 // 使用showView控件显示从网络读取的内容
    122 
    123 self.showView.text = [NSString stringWithFormat:@”%@
    %@”,
    124 
    125 content , self.showView.text];
    126 
    127 }
    128 
    129 // 再次调用readDataWithTimeout:tag:方法读取数据
    130 
    131 [sock readDataWithTimeout:-1 tag:0];
    132 
    133 }
    134 
    135 - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
    136 
    137 {
    138 
    139   //  获取UIAlertView控件上 文本框内的字符串,并将字符串赋值给myName变量
    140 
    141   myName = [alertView textFieldAtIndex:0].text;
    142 
    143   socket = [[AsyncSocket alloc] initWithDelegate:self];
    144 
    145   NSError* error = nil;
    146 
    147   int port = 30000;
    148 
    149   NSString* host = @”192.168.1.88”;
    150 
    151   // 调用connectToHost:onPort:error:方法连接指定IP地址、指定端口的服务器
    152 
    153   [socket connectToHost:host onPort:port withTimeout:2 error:&error];
    154 
    155   if(error)
    156 
    157   {
    158 
    159     NSLog(@”连接出现错误:%@”,  error);
    160 
    161 }
    162 
    163 }
    164 
    165 @end

      上面程序中的第1行红色字代码创建了一个AsyncSocket,并指定该视图控制器本身作为它的delegate对象,这意味着该视图控制器本身需要实现AsyncSocketDelegate协议,并实现该协议中特定的方法.程序中的第2行红色字代码调用了AsyncSocket的connectToHost:onPort:error: 方法来连接指定IP地址、指定端口的服务器程序。

       处理AsyncSocket网络连接及网络通信过程中的事件,该视图控制器(作为AsyncSocket的delegate)实现了onSocket:didConnectToHost:port:方法------当AsyncSocket成功连接指定服务器时激发该方法,该方法中的程序调用了AsyncSocket的readDataWithTimeout: tag:方法读取网络数据。当AsyncSocket成功读取网络数据之后,系统会自动调用视图控制器(作为AsyncSocket的delegate)的onSocket:didReadData:方法------这就实现了通过AsyncSocket读取网络数据。

  • 相关阅读:
    【OpenCV学习笔记1】OpenCV 编程简介[轉]
    latex与word比较
    【C/C++语法外功】传值&传引用&传指针
    ellen 纽奥良大学演讲
    华侨大学50年校庆校长讲话
    【专题】工业相机接口
    【C/C++参考手册】C++资源之不完全导引[轉]
    比尔盖茨_哈佛演说
    拉里.埃里森_耶鲁大学演讲
    【OpenCV学习笔记2】OpenCV 完全安装 新增VS2010+OpenCV2.1,新增VS2010+OpenCV2.3.1
  • 原文地址:https://www.cnblogs.com/congli0220/p/5057015.html
Copyright © 2011-2022 走看看