socket编程 - Asyncsocket

  1. iPhone的标准推荐是CFNetwork 库编程,其封装好的开源库是 cocoa AsyncSocket库,用它来简化CFNetwork的调用,它提供了异步操作
  2.        主要特性有:       
    1. 队列的非阻塞的读和写,而且可选超时。你可以调用它读取和写入,它会当完成后告知你
    2. 自动的socket接收。如果你调用它接收连接,它将为每个连接启动新的实例,当然,也可以立即关闭这些连接
    3. 委托(delegate)支持。错误、连接、接收、完整的读取、完整的写入、进度以及断开连接,都可以通过委托模式调用
    4. 基于run loop的,而不是线程的。虽然可以在主线程或者工作线程中使用它,但你不需要这样做。它异步的调用委托方法,使用NSRunLoop。委托方法包括socket的参数,可让你在多个实例中区分
    5. 自包含在一个类中。你无需操作流或者socket,这个类帮你做了全部
    6. 支持基于IPV4和IPV6的TCP流


  1.       加入:AsynSocket.h .m与AsynUdpSocket.h .m四个文件 及CFNetwork.framework
  2.      TCP客户端 
  3.            #import "AsyncSocket.h"

  4.            @interface HelloiPhoneViewController : UIViewController {
  5.                 UITextField    * textField;
  6.                 AsyncSocket * asyncSocket;
  7.              }
  8.             @property (retain, nonatomic) IBOutlet UITextField *textField;
  9.              - (IBAction) buttonPressed: (id)sender;
  10.              - (IBAction) textFieldDoneEditing: (id)sender;    
  11.              @end
  12.  
  13.              在需要联接地方使用connectToHost联接服务器
  14.               其中initWithDelegate的参数中self是必须。这个对象指针中的各个Socket响应的函数将被ASyncSocket所调用.initWithDelegate把将当前对象传递进去,这样只要在当前对象方法实现相应方法
  15.  
  16.                asyncSocket = [[AsyncSocket alloc] initWithDelegate:self]; 
  17.                NSError *err = nil; 
  18.                if(![asyncSocket connectToHost:host on:port error:&err]) 
  19.                 { 
  20.                    NSLog(@"Error: %@", err); 
  21.                  } 
  22.  
  23.              关于NSData对象
  24.               无论SOCKET收发都采用NSData对象.它的定义是 http://developer.apple.com/library/mac /#documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/Reference/Reference.html
  25.               NSData主要是带一个(id)data指向的数据空间和长度 length.
  26.               NSString 转换成NSData 对象
  27.  
  28.                NSData* xmlData = [@"testdata" dataUsingEncoding:NSUTF8StringEncoding];
  29.               NSData 转换成NSString对象
  30.  
  31.              NSData * data;
  32.                NSString *result = [[NSString alloc] initWithData:data         encoding:NSUTF8StringEncoding];
  33.  
  34.                发送数据
  35.                 AsyncSocket  writeData    方法来发送数据,它有如下定义
  36.     - (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  37.  
  38.                以下是一个实例语句.
  39.                NSData* aData= [@"test data" dataUsingEncoding: NSUTF8StringEncoding];
  40.               [sock writeData:aData withTimeout:-1 tag:1];

  41.               在onSocket重载函数,有如定义采用是专门用来处理SOCKET的发送数据的:
  42.                -(void)onSocket(AsyncSocket *)sock didWriteDataWithTag:(long)tag
  43.               {
  44.                     NSLog(@"thread(%),onSocket:%p didWriteDataWithTag:%d",[[NSThread currentThread] name],
  45.      sock,tag);
  46.                } 
  47.  
  48.                接收Socket数据.
  49.                在onSocket重载函数,有如定义采用是专门用来处理SOCKET的接收数据的.
  50.                -(void) onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
  51.                在中间将其转换成NSString进行显示.
  52.     NSString* aStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 
  53.     NSLog(@"===%@",aStr); 
  54.     [aStr release];

  55.       6、TCP连接读取制定长度的数据
  56.            socket连接,可能会读取固定长度的字节
  57.            [socket readDataToLength: withTimeout :tag]





  58. 各方法的解析
  59.        -(void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err;   
  60.        发生错误,socket关闭,可以在call-back过程调用"unreadData"去取得socket的最后的数据字节,当连接的时候,该委托方法在    onSocket:didAcceptNewSocket: 或者 onSocket:didConnectToHost: 之前调用

  61.       -(void)onSocketDidDisconnect:(ASyncSocket *)sock;
  62.       当socket由于或没有错误而断开连接,如果你想要在断开连接后release socket,在此方法工作,而在onSocket:willDisconnectWithError 释放则不安全

  63.        -(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket;
  64.         当产生一个socket去处理连接时调用,此方法会返回 线程上的run-loop 的新的socket和其应处理的委托,如果省略,则使用[NSRunLoop cunrrentRunLoop]

  65.           -(BOOL)onSocketWillConnect:(AsyncSocket *)sock;

  66.        -(void)onSocket:(AsyncSocket *)sock didConnectToHost :(NSString *)host port:(UINt16)port;
  67.           当socket连接正准备读和写的时候调用,host属性是一个IP地址,而不是一个DNS 名称

  68.          -(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long) tag;
  69.          当socket已完成所要求的数据读入内存时调用,如果有错误则不调用

  70.          -(void)onSocket:(Asyncsocket *)sock didReadPartialDataOfLength:(NSUInteger)partiaLength tag:(long)tag;
  71.            当一个socket读取数据,但尚未完成读操作的时候调用,如果使用 readToData: or readToLength: 方法 会发生,可以被用来更新进度条等东西

  72.             -(void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag;
  73.              当一个socket已完成请求数据的写入时候调用

  74.             -(void)onSocket:(AsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag;
  75.              当一个socket写入一些数据,但还没有完成整个写入时调用,它可以用来更新进度条等东西

  76.                -(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag elapsed:(NSTimeInterval)exapsed bytesDone:(NSUInteger)length
  77.               使用读操作已超时但还没完成时调用,此方法允许随意延迟超时,如果返回一个正的时间间隔,读取的超时将有一定量的扩展,如果不实现这个方法,或会像往常一样返回一个负的时间间隔,elapsed参数是  原超时的总和,加上先前通过这种方法添加的任何补充, length参数是 读操作到目前为止已读取的字节数, 注意,如果返回正数的话,这个方法可能被一个单独的读取多次调用

  78.                -(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutWriteWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length;
  79.                 如果一个写操作已达到其超时但还没完成时调用,同上

  80.                -(void)onSocketDidSecure:(AsyncSocket *)sock;
  81.                在socket成功完成ssl/tls协商时调用,此方法除非你使用提供startTLS方法时候才调用,
  82.     如果ssl/tls是无效的证书,socket将会立即关闭,onSocket:willDisconnectWithError:代理方法竟会与特定的ssl错误代码一起调用

  83.                -(BOOL)canSafelySetDelegate
  84.                用来查看在改变它之前,是否带有与当前的委托有悬而未决的业务(读/写)。当然,应在安全连接或接受委托之前改变委托

  85.               一旦接收或连接方法之一被调用,AsyncSocket实例会被锁定,其他接收/连接方法在没有先断开socket不会被调用
  86.               如果尝试失败或超时,这些方法要么返回NO 要么调用 onSocket:willDisconnectWithError: 或 onSockedDidDisconnect
  87.               当传入的连接被接受,AsyncSocket调用多个委托方法。这些方法按照时间顺序排列:
  88.                  1.onSocket:didAcceptNewSocket:
  89.                  2.onSocket:wantsRunLoopForNewSocket:
  90.                  3. onSocketWillConnect:
  91.                
  92.               你的服务器的代码将需要保留公认的socket(如果要接受它),最好的地方是要做到这一点可能在onSocket:didAcceptNewSocket:方法    
  93.              在读和写流已经为新接受的socket设置,onSocket:didConnectToHost:port 方法将在适当的运行循环调用
  94.              多线程注意,如果要想通过实施onSocket:wantsRunLoopForNewSocket:,移动另一个新接受的socket去到另一个循环的socket。然后,应该在调用读和写或者startTLS方法前,等待直到onSocket:didConnectToHost:port:方法。否则读和写时间原定于不正确的runloop,混乱可能会随之而来


  95.              -(BOOL)acceptOnPort:(UInit16)port error:(NSError **)errPtr;
  96.              告诉socket开始听取和接受制定端口上的连接,当一个连接到来的时候,AsyncSocket实例将调用各种委托方法,socket将听取所有可用的接口(wifi,以太网等)

  97.              -(BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error :(NSError **)errPtr;
  98.              连接给定的主机和端口,主机hostname可以是域名或者是Ip地址

  99.              -(BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError *)errPtr;
  100.              连接到一个给定的地址,制定一个sockaddr结构包裹住一个NSData对象,例如,NSData对象从NSNetService的地址方法返回,如果有一个现有的sockaddr结构,可以将它转换到一个NSData对象,像这样:
  101.  struct sockaddr sa  -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len];
  102.  struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len];

  103.              -(void)disconnect;
  104.                 立即断开,任何未处理的读或写都将被丢弃
  105.                 如果socket还没有断开,在这个方法返回之前,onSocketDidDisconnect 委托方法将会被立即调用
  106.                  注意推荐释放AsyncSocket实例的方式:
  107.                    [asyncSocket setDelegate:nil];
  108.                    [asyncSocket disconnect];
  109.                    [asyncSocket release];

  110.               -(void)disconnectAfterReading;
  111.                  在已经完成了所有悬而未决的读取时 断开,在调用之后,读取和写入方法将无用,socket将断开 即使仍有待写入

  112.               - (NSString *)connectedHost;
  113.               - (UInt16)connectedPort;
  114.               - (NSString *)localHost;
  115.               - (UInt16)localPort;
  116.                 返回本地和远程主机和端口给连接的socket,如果没有连接会返回nil或0,主机将会是一个IP地址

  117.              -(NSData *)connectedAddress
  118.              -(NSData *)localAddresss
  119.                 返回本地和远程的地址给连接的socket,指定一个socketaddr结构包裹在一个NSData对象


  120.                 readData和writeData方法不会是block(它们是异步的)
  121.                当读完成 onSocket:didReadData:withTag: 委托方法时调用
  122.                当写完成 onSocket:didWriteDataWithTag: 委托方法时调用
  123.                可以选择任何读/写操作的超时设置(为了不超时,使用负时间间隔。)
  124.                如果读/写操作超时,相应的 onSocket:shouldTimeout...委托方法被调用去选择性地允许我们去延长超时
  125.                超时后,onSocket:willDisconnectWithError: 方法被调用,紧接着是 onSocketDidDisconnect
  126.                tag是为了方便,可以使用它作为数组的索引、步数、state id 、指针等 



  127.             -(void)readDataWithTimeout:(NSTimeInterval)tiemout tag:(long)tag;
  128.               读取socket上第一次成为可用的字节,如果timeout值是负数的,读操作将不使用timeout

  129.             - (void)readDataWithTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInterger)offset tag:(long)tag;
  130.               读取socket上第一次成为可用的字节
  131.               字节将被追加到给定的字节缓冲区,从给定的偏移量开始
  132.               如果需要,给定的缓冲区大小将会自动增加
  133.               如果timeout值是负数的,读操作将不使用timeout
  134.               如果缓冲区为空,socket会为我们创建一个缓冲区
  135.               如果bufferOffset是大于给定的缓冲区的长度,该方法将无用,委托将不会被调用
  136.               如果你传递一个缓冲区,当AsyncSocket在使用它的时候你不能以任何方式改变它
  137.               完成之后,onSocket:didReadData:withTag 返回的数据将是一个给定的缓冲区的子集
  138.               也就是说,它将会被引用到被追加的给定的缓冲区的字节

  139.             -(void)readDataToLength:(NSUInterger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  140.             读取给定的字节数,如果length为0,方法将无用,委托将不会被调用

  141.             -(void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)tiemout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;
  142.             读取给定的字节数,在给定的偏移开始,字节将被追加到给定的字节缓冲区

  143.             -(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  144.             读取字节直到(包括)传入的作为分隔的"data"参数
  145.             如果传递0或者0长度的数据,"data"参数,该方法将无用,委托将不会被调用
  146.             从socket读取一行,使用"data"参数作为行的分隔符 (如HTTP的CRLF)
  147.             注意,此方法不是字符集,因此,如果一个分隔符出现,它自然可以作为进行编码的一部分,读取将提前结束

  148.             -(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;
  149.            读取字节直到(包括)传入的作为分隔的“data”参数,在给定的偏移量开始,字节将被追加到给定的字节缓冲区。
  150.            从socket读取一行,使用"data"参数作为行的分隔符(如HTTP的CRLF)

  151.            -(void)writeData:(NSData *)data withTimeout:(NSTimeInterval) timeout tag:(long)tag;
  152.           将data写入socket,当完成的时候委托被调用 

  153.            - (float)progressOfReadReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;
  154.            - (float)progressOfWriteReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;
  155.            返回当前读或写的进度,从0.0 到 1.0 或者 如果没有读/写的时候返回Nan(使用isNan来检查)
  156.    tag、done、total如果不为空的话,它们将会被填补

  157.            

  158.            - (void)startTLS:(NSDictionary *)tlsSettings;
  159.            确保使用ssl/tls连接
  160.            这方法可被随时调用,tls握手将会发生在所有悬而未决的读/写完成之后。这紧跟着一个发送依赖 StartTLS消息的协议选项,在排队升级到TLS的同一时间,而不必等待写入完成。在这个方法被调用后,任何读写计划 将会发生在安全链接
  161.            对于可能的keys和TLS设置的值是有据可查的
  162.            一些可能的keys是:
  163.               * - kCFStreamSSLLevel
  164.               * - kCFStreamSSLAllowsExpiredCertificates
  165.               * - kCFStreamSSLAllowsExpiredRoots
  166.               * - kCFStreamSSLAllowsAnyRoot
  167.               * - kCFStreamSSLValidatesCertificateChain
  168.               * - kCFStreamSSLPeerName
  169.               * - kCFStreamSSLCertificates
  170.               * - kCFStreamSSLIsServer

  171.            如果你传递空或者空字典,将使用默认的字典
  172.            默认设置将检查以确保由签署可信的第三方证书机构和没有过期的远程连接的证书
  173.            然而,它不会验证证书上的名字,除非你给它一个名字,通过kCFStreamSSLPeerName键去验证
  174.            这对安全的影响是重要的理解
  175.            想象一下你正试图创建一个到MySecureServer.com的安全连接,但因为一个被攻击的DNS服务器,所以你的socket被定向到MaliciousServer.com
  176.            如果你只是使用默认设置,MaliciousServer.com 有一个有效的证书
  177.            默认设置将无法监测到任何问题,因为证书是有效的
  178.           在这个特殊的情况下,要妥善保护你的连接,应设置kCFStreamSSLPeerName性质为MySecureServer.com.
  179.          如果事前你不知道对等的名字的远程主机(例如,你不确认它是domain.com" or "www.domain.com"),那么你可以使用默认设置来验证证书,然后在获得验证的发行后使用X509Certificate类来验证,X509Certificate类的CocoaAsyncSocket开源项目的一部分

  180.          -(void)enablePrebuffering
  181.          对于处理readDataToData请求,数据是必须从socket以小增量的方式读取出来的
  182.          性能通过允许AsyncSocket去一次性读大块的数据和存储任何一个小的内部缓冲区溢出的东西来大大提高
  183.          这被称为预缓冲,就好像一些数据在你要求它之前就可能被读取出来
  184.          如果你经常使用readDataToData,使用预缓冲会有更好的性能,尤其是在iphone上
  185.          默认的预缓冲状态是由DEFAULT_PREBUFFERING 定义控制的,强烈建议设置其为yes
  186.          这方法存在一些预缓冲需要一些不可预见的原因被默认禁用的情况,这时,这种方法存在允许当就绪时,可轻松启用预缓冲

  187.           -(BOOL)moveToRunLoop:(NSRunLoop *)runLoop;
  188.           当你创建一个AsyncSocket,它被添加到当前线程runloop
  189.           对于手动创建的socket,在线程上你打算使用它,它是最容易简单的创建的线程上的socket
  190.           当一个新的socket被接受,委托方法 onSocket:wantsRunLoopForNewSocket 会被调用 允许你在一个单独的线程上放置socket,这个工作最好结合在同一个线程池设计
  191.           如果,但是,在一个单独的线程上,在之后的时间,你需要移动一个socket,这个方法可以用来完成任务
  192.           此方法必须从 当前运行的 线程/runloop 的socket 调用
  193.           注意:此方法调用后,所有进一步的方法应该从给定的runloop上调用这个对象
  194.           此外,所有委托调用将会发送到给定的runloop


  195.           - (BOOL)setRunLoopModes:(NSArray *)runLoopModes;
  196.           - (BOOL)addRunLoopMode:(NSString *)runLoopMode;
  197.           - (BOOL)removeRunLoopMode:(NSString *)runLoopMode;
  198.            允许你配置 socket 使用的 运行循环模式
  199.            运行循环模式设置默认是NSRunLoopCommonModes
  200.            如果你想你的socket 在其他模式下继续操作,你可能需要添加模式 NSModalPanelRunLoopMode 或者 NSEventTrackingRunLoopMode ,或者你可能只想使用 NSRunLoopCommonModes
  201.            可接受的socket将自动 继承相同的运行循环模式就像侦听socket
  202.            注意:NSRunLoopCommonModes 定义在10.5,对于之前的版本可使用 kCFRunLoopCommonModes

  203.           -(NSArray *)runLoopModes
  204.             返回当前正在运行的循环模式的AsyncSocket实例, run loop modes的默认设置是NSDefaultRunLoopMode

  205.           -(NSData *)unreadData;
  206.          一个错误的事件,在 onSocket:willDisconnectWithError: 将会被调用 去读取留在socket上的任何数据

  207.           + (NSData *)CRLFData;   // 0x0D0A
  208.   



  209. 各方法的解析
  210.        -(void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err;   
  211.        发生错误,socket关闭,可以在call-back过程调用"unreadData"去取得socket的最后的数据字节,当连接的时候,该委托方法在    onSocket:didAcceptNewSocket: 或者 onSocket:didConnectToHost: 之前调用

  212.       -(void)onSocketDidDisconnect:(ASyncSocket *)sock;
  213.       当socket由于或没有错误而断开连接,如果你想要在断开连接后release socket,在此方法工作,而在onSocket:willDisconnectWithError 释放则不安全

  214.        -(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket;
  215.         当产生一个socket去处理连接时调用,此方法会返回 线程上的run-loop 的新的socket和其应处理的委托,如果省略,则使用[NSRunLoop cunrrentRunLoop]

  216.           -(BOOL)onSocketWillConnect:(AsyncSocket *)sock;

  217.        -(void)onSocket:(AsyncSocket *)sock didConnectToHost :(NSString *)host port:(UINt16)port;
  218.           当socket连接正准备读和写的时候调用,host属性是一个IP地址,而不是一个DNS 名称

  219.          -(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long) tag;
  220.          当socket已完成所要求的数据读入内存时调用,如果有错误则不调用

  221.          -(void)onSocket:(Asyncsocket *)sock didReadPartialDataOfLength:(NSUInteger)partiaLength tag:(long)tag;
  222.            当一个socket读取数据,但尚未完成读操作的时候调用,如果使用 readToData: or readToLength: 方法 会发生,可以被用来更新进度条等东西

  223.             -(void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag;
  224.              当一个socket已完成请求数据的写入时候调用

  225.             -(void)onSocket:(AsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag;
  226.              当一个socket写入一些数据,但还没有完成整个写入时调用,它可以用来更新进度条等东西

  227.                -(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag elapsed:(NSTimeInterval)exapsed bytesDone:(NSUInteger)length
  228.               使用读操作已超时但还没完成时调用,此方法允许随意延迟超时,如果返回一个正的时间间隔,读取的超时将有一定量的扩展,如果不实现这个方法,或会像往常一样返回一个负的时间间隔,elapsed参数是  原超时的总和,加上先前通过这种方法添加的任何补充, length参数是 读操作到目前为止已读取的字节数, 注意,如果返回正数的话,这个方法可能被一个单独的读取多次调用

  229.                -(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutWriteWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length;
  230.                 如果一个写操作已达到其超时但还没完成时调用,同上

  231.                -(void)onSocketDidSecure:(AsyncSocket *)sock;
  232.                在socket成功完成ssl/tls协商时调用,此方法除非你使用提供startTLS方法时候才调用,
  233.     如果ssl/tls是无效的证书,socket将会立即关闭,onSocket:willDisconnectWithError:代理方法竟会与特定的ssl错误代码一起调用

  234.                -(BOOL)canSafelySetDelegate
  235.                用来查看在改变它之前,是否带有与当前的委托有悬而未决的业务(读/写)。当然,应在安全连接或接受委托之前改变委托

  236.               一旦接收或连接方法之一被调用,AsyncSocket实例会被锁定,其他接收/连接方法在没有先断开socket不会被调用
  237.               如果尝试失败或超时,这些方法要么返回NO 要么调用 onSocket:willDisconnectWithError: 或 onSockedDidDisconnect
  238.               当传入的连接被接受,AsyncSocket调用多个委托方法。这些方法按照时间顺序排列:
  239.                  1.onSocket:didAcceptNewSocket:
  240.                  2.onSocket:wantsRunLoopForNewSocket:
  241.                  3. onSocketWillConnect:
  242.                
  243.               你的服务器的代码将需要保留公认的socket(如果要接受它),最好的地方是要做到这一点可能在onSocket:didAcceptNewSocket:方法    
  244.              在读和写流已经为新接受的socket设置,onSocket:didConnectToHost:port 方法将在适当的运行循环调用
  245.              多线程注意,如果要想通过实施onSocket:wantsRunLoopForNewSocket:,移动另一个新接受的socket去到另一个循环的socket。然后,应该在调用读和写或者startTLS方法前,等待直到onSocket:didConnectToHost:port:方法。否则读和写时间原定于不正确的runloop,混乱可能会随之而来


  246.              -(BOOL)acceptOnPort:(UInit16)port error:(NSError **)errPtr;
  247.              告诉socket开始听取和接受制定端口上的连接,当一个连接到来的时候,AsyncSocket实例将调用各种委托方法,socket将听取所有可用的接口(wifi,以太网等)

  248.              -(BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error :(NSError **)errPtr;
  249.              连接给定的主机和端口,主机hostname可以是域名或者是Ip地址

  250.              -(BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError *)errPtr;
  251.              连接到一个给定的地址,制定一个sockaddr结构包裹住一个NSData对象,例如,NSData对象从NSNetService的地址方法返回,如果有一个现有的sockaddr结构,可以将它转换到一个NSData对象,像这样:
  252.  struct sockaddr sa  -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len];
  253.  struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len];

  254.              -(void)disconnect;
  255.                 立即断开,任何未处理的读或写都将被丢弃
  256.                 如果socket还没有断开,在这个方法返回之前,onSocketDidDisconnect 委托方法将会被立即调用
  257.                  注意推荐释放AsyncSocket实例的方式:
  258.                    [asyncSocket setDelegate:nil];
  259.                    [asyncSocket disconnect];
  260.                    [asyncSocket release];

  261.               -(void)disconnectAfterReading;
  262.                  在已经完成了所有悬而未决的读取时 断开,在调用之后,读取和写入方法将无用,socket将断开 即使仍有待写入

  263.               - (NSString *)connectedHost;
  264.               - (UInt16)connectedPort;
  265.               - (NSString *)localHost;
  266.               - (UInt16)localPort;
  267.                 返回本地和远程主机和端口给连接的socket,如果没有连接会返回nil或0,主机将会是一个IP地址

  268.              -(NSData *)connectedAddress
  269.              -(NSData *)localAddresss
  270.                 返回本地和远程的地址给连接的socket,指定一个socketaddr结构包裹在一个NSData对象


  271.                 readData和writeData方法不会是block(它们是异步的)
  272.                当读完成 onSocket:didReadData:withTag: 委托方法时调用
  273.                当写完成 onSocket:didWriteDataWithTag: 委托方法时调用
  274.                可以选择任何读/写操作的超时设置(为了不超时,使用负时间间隔。)
  275.                如果读/写操作超时,相应的 onSocket:shouldTimeout...委托方法被调用去选择性地允许我们去延长超时
  276.                超时后,onSocket:willDisconnectWithError: 方法被调用,紧接着是 onSocketDidDisconnect
  277.                tag是为了方便,可以使用它作为数组的索引、步数、state id 、指针等 



  278.             -(void)readDataWithTimeout:(NSTimeInterval)tiemout tag:(long)tag;
  279.               读取socket上第一次成为可用的字节,如果timeout值是负数的,读操作将不使用timeout

  280.             - (void)readDataWithTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInterger)offset tag:(long)tag;
  281.               读取socket上第一次成为可用的字节
  282.               字节将被追加到给定的字节缓冲区,从给定的偏移量开始
  283.               如果需要,给定的缓冲区大小将会自动增加
  284.               如果timeout值是负数的,读操作将不使用timeout
  285.               如果缓冲区为空,socket会为我们创建一个缓冲区
  286.               如果bufferOffset是大于给定的缓冲区的长度,该方法将无用,委托将不会被调用
  287.               如果你传递一个缓冲区,当AsyncSocket在使用它的时候你不能以任何方式改变它
  288.               完成之后,onSocket:didReadData:withTag 返回的数据将是一个给定的缓冲区的子集
  289.               也就是说,它将会被引用到被追加的给定的缓冲区的字节

  290.             -(void)readDataToLength:(NSUInterger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  291.             读取给定的字节数,如果length为0,方法将无用,委托将不会被调用

  292.             -(void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)tiemout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;
  293.             读取给定的字节数,在给定的偏移开始,字节将被追加到给定的字节缓冲区

  294.             -(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  295.             读取字节直到(包括)传入的作为分隔的"data"参数
  296.             如果传递0或者0长度的数据,"data"参数,该方法将无用,委托将不会被调用
  297.             从socket读取一行,使用"data"参数作为行的分隔符 (如HTTP的CRLF)
  298.             注意,此方法不是字符集,因此,如果一个分隔符出现,它自然可以作为进行编码的一部分,读取将提前结束

  299.             -(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;
  300.            读取字节直到(包括)传入的作为分隔的“data”参数,在给定的偏移量开始,字节将被追加到给定的字节缓冲区。
  301.            从socket读取一行,使用"data"参数作为行的分隔符(如HTTP的CRLF)

  302.            -(void)writeData:(NSData *)data withTimeout:(NSTimeInterval) timeout tag:(long)tag;
  303.           将data写入socket,当完成的时候委托被调用 

  304.            - (float)progressOfReadReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;
  305.            - (float)progressOfWriteReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;
  306.            返回当前读或写的进度,从0.0 到 1.0 或者 如果没有读/写的时候返回Nan(使用isNan来检查)
  307.    tag、done、total如果不为空的话,它们将会被填补

  308.            

  309.            - (void)startTLS:(NSDictionary *)tlsSettings;
  310.            确保使用ssl/tls连接
  311.            这方法可被随时调用,tls握手将会发生在所有悬而未决的读/写完成之后。这紧跟着一个发送依赖 StartTLS消息的协议选项,在排队升级到TLS的同一时间,而不必等待写入完成。在这个方法被调用后,任何读写计划 将会发生在安全链接
  312.            对于可能的keys和TLS设置的值是有据可查的
  313.            一些可能的keys是:
  314.               * - kCFStreamSSLLevel
  315.               * - kCFStreamSSLAllowsExpiredCertificates
  316.               * - kCFStreamSSLAllowsExpiredRoots
  317.               * - kCFStreamSSLAllowsAnyRoot
  318.               * - kCFStreamSSLValidatesCertificateChain
  319.               * - kCFStreamSSLPeerName
  320.               * - kCFStreamSSLCertificates
  321.               * - kCFStreamSSLIsServer

  322.            如果你传递空或者空字典,将使用默认的字典
  323.            默认设置将检查以确保由签署可信的第三方证书机构和没有过期的远程连接的证书
  324.            然而,它不会验证证书上的名字,除非你给它一个名字,通过kCFStreamSSLPeerName键去验证
  325.            这对安全的影响是重要的理解
  326.            想象一下你正试图创建一个到MySecureServer.com的安全连接,但因为一个被攻击的DNS服务器,所以你的socket被定向到MaliciousServer.com
  327.            如果你只是使用默认设置,MaliciousServer.com 有一个有效的证书
  328.            默认设置将无法监测到任何问题,因为证书是有效的
  329.           在这个特殊的情况下,要妥善保护你的连接,应设置kCFStreamSSLPeerName性质为MySecureServer.com.
  330.          如果事前你不知道对等的名字的远程主机(例如,你不确认它是domain.com" or "www.domain.com"),那么你可以使用默认设置来验证证书,然后在获得验证的发行后使用X509Certificate类来验证,X509Certificate类的CocoaAsyncSocket开源项目的一部分

  331.          -(void)enablePrebuffering
  332.          对于处理readDataToData请求,数据是必须从socket以小增量的方式读取出来的
  333.          性能通过允许AsyncSocket去一次性读大块的数据和存储任何一个小的内部缓冲区溢出的东西来大大提高
  334.          这被称为预缓冲,就好像一些数据在你要求它之前就可能被读取出来
  335.          如果你经常使用readDataToData,使用预缓冲会有更好的性能,尤其是在iphone上
  336.          默认的预缓冲状态是由DEFAULT_PREBUFFERING 定义控制的,强烈建议设置其为yes
  337.          这方法存在一些预缓冲需要一些不可预见的原因被默认禁用的情况,这时,这种方法存在允许当就绪时,可轻松启用预缓冲

  338.           -(BOOL)moveToRunLoop:(NSRunLoop *)runLoop;
  339.           当你创建一个AsyncSocket,它被添加到当前线程runloop
  340.           对于手动创建的socket,在线程上你打算使用它,它是最容易简单的创建的线程上的socket
  341.           当一个新的socket被接受,委托方法 onSocket:wantsRunLoopForNewSocket 会被调用 允许你在一个单独的线程上放置socket,这个工作最好结合在同一个线程池设计
  342.           如果,但是,在一个单独的线程上,在之后的时间,你需要移动一个socket,这个方法可以用来完成任务
  343.           此方法必须从 当前运行的 线程/runloop 的socket 调用
  344.           注意:此方法调用后,所有进一步的方法应该从给定的runloop上调用这个对象
  345.           此外,所有委托调用将会发送到给定的runloop


  346.           - (BOOL)setRunLoopModes:(NSArray *)runLoopModes;
  347.           - (BOOL)addRunLoopMode:(NSString *)runLoopMode;
  348.           - (BOOL)removeRunLoopMode:(NSString *)runLoopMode;
  349.            允许你配置 socket 使用的 运行循环模式
  350.            运行循环模式设置默认是NSRunLoopCommonModes
  351.            如果你想你的socket 在其他模式下继续操作,你可能需要添加模式 NSModalPanelRunLoopMode 或者 NSEventTrackingRunLoopMode ,或者你可能只想使用 NSRunLoopCommonModes
  352.            可接受的socket将自动 继承相同的运行循环模式就像侦听socket
  353.            注意:NSRunLoopCommonModes 定义在10.5,对于之前的版本可使用 kCFRunLoopCommonModes

  354.           -(NSArray *)runLoopModes
  355.             返回当前正在运行的循环模式的AsyncSocket实例, run loop modes的默认设置是NSDefaultRunLoopMode

  356.           -(NSData *)unreadData;
  357.          一个错误的事件,在 onSocket:willDisconnectWithError: 将会被调用 去读取留在socket上的任何数据

  358.           + (NSData *)CRLFData;   // 0x0D0A
  359.   


  360. 各方法的解析
  361.        -(void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err;   
  362.        发生错误,socket关闭,可以在call-back过程调用"unreadData"去取得socket的最后的数据字节,当连接的时候,该委托方法在    onSocket:didAcceptNewSocket: 或者 onSocket:didConnectToHost: 之前调用

  363.       -(void)onSocketDidDisconnect:(ASyncSocket *)sock;
  364.       当socket由于或没有错误而断开连接,如果你想要在断开连接后release socket,在此方法工作,而在onSocket:willDisconnectWithError 释放则不安全

  365.        -(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket;
  366.         当产生一个socket去处理连接时调用,此方法会返回 线程上的run-loop 的新的socket和其应处理的委托,如果省略,则使用[NSRunLoop cunrrentRunLoop]

  367.           -(BOOL)onSocketWillConnect:(AsyncSocket *)sock;

  368.        -(void)onSocket:(AsyncSocket *)sock didConnectToHost :(NSString *)host port:(UINt16)port;
  369.           当socket连接正准备读和写的时候调用,host属性是一个IP地址,而不是一个DNS 名称

  370.          -(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long) tag;
  371.          当socket已完成所要求的数据读入内存时调用,如果有错误则不调用

  372.          -(void)onSocket:(Asyncsocket *)sock didReadPartialDataOfLength:(NSUInteger)partiaLength tag:(long)tag;
  373.            当一个socket读取数据,但尚未完成读操作的时候调用,如果使用 readToData: or readToLength: 方法 会发生,可以被用来更新进度条等东西

  374.             -(void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag;
  375.              当一个socket已完成请求数据的写入时候调用

  376.             -(void)onSocket:(AsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag;
  377.              当一个socket写入一些数据,但还没有完成整个写入时调用,它可以用来更新进度条等东西

  378.                -(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag elapsed:(NSTimeInterval)exapsed bytesDone:(NSUInteger)length
  379.               使用读操作已超时但还没完成时调用,此方法允许随意延迟超时,如果返回一个正的时间间隔,读取的超时将有一定量的扩展,如果不实现这个方法,或会像往常一样返回一个负的时间间隔,elapsed参数是  原超时的总和,加上先前通过这种方法添加的任何补充, length参数是 读操作到目前为止已读取的字节数, 注意,如果返回正数的话,这个方法可能被一个单独的读取多次调用

  380.                -(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutWriteWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length;
  381.                 如果一个写操作已达到其超时但还没完成时调用,同上

  382.                -(void)onSocketDidSecure:(AsyncSocket *)sock;
  383.                在socket成功完成ssl/tls协商时调用,此方法除非你使用提供startTLS方法时候才调用,
  384.     如果ssl/tls是无效的证书,socket将会立即关闭,onSocket:willDisconnectWithError:代理方法竟会与特定的ssl错误代码一起调用

  385.                -(BOOL)canSafelySetDelegate
  386.                用来查看在改变它之前,是否带有与当前的委托有悬而未决的业务(读/写)。当然,应在安全连接或接受委托之前改变委托

  387.               一旦接收或连接方法之一被调用,AsyncSocket实例会被锁定,其他接收/连接方法在没有先断开socket不会被调用
  388.               如果尝试失败或超时,这些方法要么返回NO 要么调用 onSocket:willDisconnectWithError: 或 onSockedDidDisconnect
  389.               当传入的连接被接受,AsyncSocket调用多个委托方法。这些方法按照时间顺序排列:
  390.                  1.onSocket:didAcceptNewSocket:
  391.                  2.onSocket:wantsRunLoopForNewSocket:
  392.                  3. onSocketWillConnect:
  393.                
  394.               你的服务器的代码将需要保留公认的socket(如果要接受它),最好的地方是要做到这一点可能在onSocket:didAcceptNewSocket:方法    
  395.              在读和写流已经为新接受的socket设置,onSocket:didConnectToHost:port 方法将在适当的运行循环调用
  396.              多线程注意,如果要想通过实施onSocket:wantsRunLoopForNewSocket:,移动另一个新接受的socket去到另一个循环的socket。然后,应该在调用读和写或者startTLS方法前,等待直到onSocket:didConnectToHost:port:方法。否则读和写时间原定于不正确的runloop,混乱可能会随之而来


  397.              -(BOOL)acceptOnPort:(UInit16)port error:(NSError **)errPtr;
  398.              告诉socket开始听取和接受制定端口上的连接,当一个连接到来的时候,AsyncSocket实例将调用各种委托方法,socket将听取所有可用的接口(wifi,以太网等)

  399.              -(BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error :(NSError **)errPtr;
  400.              连接给定的主机和端口,主机hostname可以是域名或者是Ip地址

  401.              -(BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError *)errPtr;
  402.              连接到一个给定的地址,制定一个sockaddr结构包裹住一个NSData对象,例如,NSData对象从NSNetService的地址方法返回,如果有一个现有的sockaddr结构,可以将它转换到一个NSData对象,像这样:
  403.  struct sockaddr sa  -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len];
  404.  struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len];

  405.              -(void)disconnect;
  406.                 立即断开,任何未处理的读或写都将被丢弃
  407.                 如果socket还没有断开,在这个方法返回之前,onSocketDidDisconnect 委托方法将会被立即调用
  408.                  注意推荐释放AsyncSocket实例的方式:
  409.                    [asyncSocket setDelegate:nil];
  410.                    [asyncSocket disconnect];
  411.                    [asyncSocket release];

  412.               -(void)disconnectAfterReading;
  413.                  在已经完成了所有悬而未决的读取时 断开,在调用之后,读取和写入方法将无用,socket将断开 即使仍有待写入

  414.               - (NSString *)connectedHost;
  415.               - (UInt16)connectedPort;
  416.               - (NSString *)localHost;
  417.               - (UInt16)localPort;
  418.                 返回本地和远程主机和端口给连接的socket,如果没有连接会返回nil或0,主机将会是一个IP地址

  419.              -(NSData *)connectedAddress
  420.              -(NSData *)localAddresss
  421.                 返回本地和远程的地址给连接的socket,指定一个socketaddr结构包裹在一个NSData对象


  422.                 readData和writeData方法不会是block(它们是异步的)
  423.                当读完成 onSocket:didReadData:withTag: 委托方法时调用
  424.                当写完成 onSocket:didWriteDataWithTag: 委托方法时调用
  425.                可以选择任何读/写操作的超时设置(为了不超时,使用负时间间隔。)
  426.                如果读/写操作超时,相应的 onSocket:shouldTimeout...委托方法被调用去选择性地允许我们去延长超时
  427.                超时后,onSocket:willDisconnectWithError: 方法被调用,紧接着是 onSocketDidDisconnect
  428.                tag是为了方便,可以使用它作为数组的索引、步数、state id 、指针等 



  429.             -(void)readDataWithTimeout:(NSTimeInterval)tiemout tag:(long)tag;
  430.               读取socket上第一次成为可用的字节,如果timeout值是负数的,读操作将不使用timeout

  431.             - (void)readDataWithTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInterger)offset tag:(long)tag;
  432.               读取socket上第一次成为可用的字节
  433.               字节将被追加到给定的字节缓冲区,从给定的偏移量开始
  434.               如果需要,给定的缓冲区大小将会自动增加
  435.               如果timeout值是负数的,读操作将不使用timeout
  436.               如果缓冲区为空,socket会为我们创建一个缓冲区
  437.               如果bufferOffset是大于给定的缓冲区的长度,该方法将无用,委托将不会被调用
  438.               如果你传递一个缓冲区,当AsyncSocket在使用它的时候你不能以任何方式改变它
  439.               完成之后,onSocket:didReadData:withTag 返回的数据将是一个给定的缓冲区的子集
  440.               也就是说,它将会被引用到被追加的给定的缓冲区的字节

  441.             -(void)readDataToLength:(NSUInterger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  442.             读取给定的字节数,如果length为0,方法将无用,委托将不会被调用

  443.             -(void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)tiemout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;
  444.             读取给定的字节数,在给定的偏移开始,字节将被追加到给定的字节缓冲区

  445.             -(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  446.             读取字节直到(包括)传入的作为分隔的"data"参数
  447.             如果传递0或者0长度的数据,"data"参数,该方法将无用,委托将不会被调用
  448.             从socket读取一行,使用"data"参数作为行的分隔符 (如HTTP的CRLF)
  449.             注意,此方法不是字符集,因此,如果一个分隔符出现,它自然可以作为进行编码的一部分,读取将提前结束

  450.             -(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;
  451.            读取字节直到(包括)传入的作为分隔的“data”参数,在给定的偏移量开始,字节将被追加到给定的字节缓冲区。
  452.            从socket读取一行,使用"data"参数作为行的分隔符(如HTTP的CRLF)

  453.            -(void)writeData:(NSData *)data withTimeout:(NSTimeInterval) timeout tag:(long)tag;
  454.           将data写入socket,当完成的时候委托被调用 

  455.            - (float)progressOfReadReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;
  456.            - (float)progressOfWriteReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;
  457.            返回当前读或写的进度,从0.0 到 1.0 或者 如果没有读/写的时候返回Nan(使用isNan来检查)
  458.    tag、done、total如果不为空的话,它们将会被填补

  459.            

  460.            - (void)startTLS:(NSDictionary *)tlsSettings;
  461.            确保使用ssl/tls连接
  462.            这方法可被随时调用,tls握手将会发生在所有悬而未决的读/写完成之后。这紧跟着一个发送依赖 StartTLS消息的协议选项,在排队升级到TLS的同一时间,而不必等待写入完成。在这个方法被调用后,任何读写计划 将会发生在安全链接
  463.            对于可能的keys和TLS设置的值是有据可查的
  464.            一些可能的keys是:
  465.               * - kCFStreamSSLLevel
  466.               * - kCFStreamSSLAllowsExpiredCertificates
  467.               * - kCFStreamSSLAllowsExpiredRoots
  468.               * - kCFStreamSSLAllowsAnyRoot
  469.               * - kCFStreamSSLValidatesCertificateChain
  470.               * - kCFStreamSSLPeerName
  471.               * - kCFStreamSSLCertificates
  472.               * - kCFStreamSSLIsServer

  473.            如果你传递空或者空字典,将使用默认的字典
  474.            默认设置将检查以确保由签署可信的第三方证书机构和没有过期的远程连接的证书
  475.            然而,它不会验证证书上的名字,除非你给它一个名字,通过kCFStreamSSLPeerName键去验证
  476.            这对安全的影响是重要的理解
  477.            想象一下你正试图创建一个到MySecureServer.com的安全连接,但因为一个被攻击的DNS服务器,所以你的socket被定向到MaliciousServer.com
  478.            如果你只是使用默认设置,MaliciousServer.com 有一个有效的证书
  479.            默认设置将无法监测到任何问题,因为证书是有效的
  480.           在这个特殊的情况下,要妥善保护你的连接,应设置kCFStreamSSLPeerName性质为MySecureServer.com.
  481.          如果事前你不知道对等的名字的远程主机(例如,你不确认它是domain.com" or "www.domain.com"),那么你可以使用默认设置来验证证书,然后在获得验证的发行后使用X509Certificate类来验证,X509Certificate类的CocoaAsyncSocket开源项目的一部分

  482.          -(void)enablePrebuffering
  483.          对于处理readDataToData请求,数据是必须从socket以小增量的方式读取出来的
  484.          性能通过允许AsyncSocket去一次性读大块的数据和存储任何一个小的内部缓冲区溢出的东西来大大提高
  485.          这被称为预缓冲,就好像一些数据在你要求它之前就可能被读取出来
  486.          如果你经常使用readDataToData,使用预缓冲会有更好的性能,尤其是在iphone上
  487.          默认的预缓冲状态是由DEFAULT_PREBUFFERING 定义控制的,强烈建议设置其为yes
  488.          这方法存在一些预缓冲需要一些不可预见的原因被默认禁用的情况,这时,这种方法存在允许当就绪时,可轻松启用预缓冲

  489.           -(BOOL)moveToRunLoop:(NSRunLoop *)runLoop;
  490.           当你创建一个AsyncSocket,它被添加到当前线程runloop
  491.           对于手动创建的socket,在线程上你打算使用它,它是最容易简单的创建的线程上的socket
  492.           当一个新的socket被接受,委托方法 onSocket:wantsRunLoopForNewSocket 会被调用 允许你在一个单独的线程上放置socket,这个工作最好结合在同一个线程池设计
  493.           如果,但是,在一个单独的线程上,在之后的时间,你需要移动一个socket,这个方法可以用来完成任务
  494.           此方法必须从 当前运行的 线程/runloop 的socket 调用
  495.           注意:此方法调用后,所有进一步的方法应该从给定的runloop上调用这个对象
  496.           此外,所有委托调用将会发送到给定的runloop


  497.           - (BOOL)setRunLoopModes:(NSArray *)runLoopModes;
  498.           - (BOOL)addRunLoopMode:(NSString *)runLoopMode;
  499.           - (BOOL)removeRunLoopMode:(NSString *)runLoopMode;
  500.            允许你配置 socket 使用的 运行循环模式
  501.            运行循环模式设置默认是NSRunLoopCommonModes
  502.            如果你想你的socket 在其他模式下继续操作,你可能需要添加模式 NSModalPanelRunLoopMode 或者 NSEventTrackingRunLoopMode ,或者你可能只想使用 NSRunLoopCommonModes
  503.            可接受的socket将自动 继承相同的运行循环模式就像侦听socket
  504.            注意:NSRunLoopCommonModes 定义在10.5,对于之前的版本可使用 kCFRunLoopCommonModes

  505.           -(NSArray *)runLoopModes
  506.             返回当前正在运行的循环模式的AsyncSocket实例, run loop modes的默认设置是NSDefaultRunLoopMode

  507.           -(NSData *)unreadData;
  508.          一个错误的事件,在 onSocket:willDisconnectWithError: 将会被调用 去读取留在socket上的任何数据

  509.           + (NSData *)CRLFData;   // 0x0D0A
  510.   

  511. 各方法的解析
  512.        -(void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err;   
  513.        发生错误,socket关闭,可以在call-back过程调用"unreadData"去取得socket的最后的数据字节,当连接的时候,该委托方法在    onSocket:didAcceptNewSocket: 或者 onSocket:didConnectToHost: 之前调用

  514.       -(void)onSocketDidDisconnect:(ASyncSocket *)sock;
  515.       当socket由于或没有错误而断开连接,如果你想要在断开连接后release socket,在此方法工作,而在onSocket:willDisconnectWithError 释放则不安全

  516.        -(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket;
  517.         当产生一个socket去处理连接时调用,此方法会返回 线程上的run-loop 的新的socket和其应处理的委托,如果省略,则使用[NSRunLoop cunrrentRunLoop]

  518.           -(BOOL)onSocketWillConnect:(AsyncSocket *)sock;

  519.        -(void)onSocket:(AsyncSocket *)sock didConnectToHost :(NSString *)host port:(UINt16)port;
  520.           当socket连接正准备读和写的时候调用,host属性是一个IP地址,而不是一个DNS 名称

  521.          -(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long) tag;
  522.          当socket已完成所要求的数据读入内存时调用,如果有错误则不调用

  523.          -(void)onSocket:(Asyncsocket *)sock didReadPartialDataOfLength:(NSUInteger)partiaLength tag:(long)tag;
  524.            当一个socket读取数据,但尚未完成读操作的时候调用,如果使用 readToData: or readToLength: 方法 会发生,可以被用来更新进度条等东西

  525.             -(void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag;
  526.              当一个socket已完成请求数据的写入时候调用

  527.             -(void)onSocket:(AsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag;
  528.              当一个socket写入一些数据,但还没有完成整个写入时调用,它可以用来更新进度条等东西

  529.                -(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag elapsed:(NSTimeInterval)exapsed bytesDone:(NSUInteger)length
  530.               使用读操作已超时但还没完成时调用,此方法允许随意延迟超时,如果返回一个正的时间间隔,读取的超时将有一定量的扩展,如果不实现这个方法,或会像往常一样返回一个负的时间间隔,elapsed参数是  原超时的总和,加上先前通过这种方法添加的任何补充, length参数是 读操作到目前为止已读取的字节数, 注意,如果返回正数的话,这个方法可能被一个单独的读取多次调用

  531.                -(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutWriteWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length;
  532.                 如果一个写操作已达到其超时但还没完成时调用,同上

  533.                -(void)onSocketDidSecure:(AsyncSocket *)sock;
  534.                在socket成功完成ssl/tls协商时调用,此方法除非你使用提供startTLS方法时候才调用,
  535.     如果ssl/tls是无效的证书,socket将会立即关闭,onSocket:willDisconnectWithError:代理方法竟会与特定的ssl错误代码一起调用

  536.                -(BOOL)canSafelySetDelegate
  537.                用来查看在改变它之前,是否带有与当前的委托有悬而未决的业务(读/写)。当然,应在安全连接或接受委托之前改变委托

  538.               一旦接收或连接方法之一被调用,AsyncSocket实例会被锁定,其他接收/连接方法在没有先断开socket不会被调用
  539.               如果尝试失败或超时,这些方法要么返回NO 要么调用 onSocket:willDisconnectWithError: 或 onSockedDidDisconnect
  540.               当传入的连接被接受,AsyncSocket调用多个委托方法。这些方法按照时间顺序排列:
  541.                  1.onSocket:didAcceptNewSocket:
  542.                  2.onSocket:wantsRunLoopForNewSocket:
  543.                  3. onSocketWillConnect:
  544.                
  545.               你的服务器的代码将需要保留公认的socket(如果要接受它),最好的地方是要做到这一点可能在onSocket:didAcceptNewSocket:方法    
  546.              在读和写流已经为新接受的socket设置,onSocket:didConnectToHost:port 方法将在适当的运行循环调用
  547.              多线程注意,如果要想通过实施onSocket:wantsRunLoopForNewSocket:,移动另一个新接受的socket去到另一个循环的socket。然后,应该在调用读和写或者startTLS方法前,等待直到onSocket:didConnectToHost:port:方法。否则读和写时间原定于不正确的runloop,混乱可能会随之而来


  548.              -(BOOL)acceptOnPort:(UInit16)port error:(NSError **)errPtr;
  549.              告诉socket开始听取和接受制定端口上的连接,当一个连接到来的时候,AsyncSocket实例将调用各种委托方法,socket将听取所有可用的接口(wifi,以太网等)

  550.              -(BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error :(NSError **)errPtr;
  551.              连接给定的主机和端口,主机hostname可以是域名或者是Ip地址

  552.              -(BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError *)errPtr;
  553.              连接到一个给定的地址,制定一个sockaddr结构包裹住一个NSData对象,例如,NSData对象从NSNetService的地址方法返回,如果有一个现有的sockaddr结构,可以将它转换到一个NSData对象,像这样:
  554.  struct sockaddr sa  -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len];
  555.  struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len];

  556.              -(void)disconnect;
  557.                 立即断开,任何未处理的读或写都将被丢弃
  558.                 如果socket还没有断开,在这个方法返回之前,onSocketDidDisconnect 委托方法将会被立即调用
  559.                  注意推荐释放AsyncSocket实例的方式:
  560.                    [asyncSocket setDelegate:nil];
  561.                    [asyncSocket disconnect];
  562.                    [asyncSocket release];

  563.               -(void)disconnectAfterReading;
  564.                  在已经完成了所有悬而未决的读取时 断开,在调用之后,读取和写入方法将无用,socket将断开 即使仍有待写入

  565.               - (NSString *)connectedHost;
  566.               - (UInt16)connectedPort;
  567.               - (NSString *)localHost;
  568.               - (UInt16)localPort;
  569.                 返回本地和远程主机和端口给连接的socket,如果没有连接会返回nil或0,主机将会是一个IP地址

  570.              -(NSData *)connectedAddress
  571.              -(NSData *)localAddresss
  572.                 返回本地和远程的地址给连接的socket,指定一个socketaddr结构包裹在一个NSData对象


  573.                 readData和writeData方法不会是block(它们是异步的)
  574.                当读完成 onSocket:didReadData:withTag: 委托方法时调用
  575.                当写完成 onSocket:didWriteDataWithTag: 委托方法时调用
  576.                可以选择任何读/写操作的超时设置(为了不超时,使用负时间间隔。)
  577.                如果读/写操作超时,相应的 onSocket:shouldTimeout...委托方法被调用去选择性地允许我们去延长超时
  578.                超时后,onSocket:willDisconnectWithError: 方法被调用,紧接着是 onSocketDidDisconnect
  579.                tag是为了方便,可以使用它作为数组的索引、步数、state id 、指针等 



  580.             -(void)readDataWithTimeout:(NSTimeInterval)tiemout tag:(long)tag;
  581.               读取socket上第一次成为可用的字节,如果timeout值是负数的,读操作将不使用timeout

  582.             - (void)readDataWithTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInterger)offset tag:(long)tag;
  583.               读取socket上第一次成为可用的字节
  584.               字节将被追加到给定的字节缓冲区,从给定的偏移量开始
  585.               如果需要,给定的缓冲区大小将会自动增加
  586.               如果timeout值是负数的,读操作将不使用timeout
  587.               如果缓冲区为空,socket会为我们创建一个缓冲区
  588.               如果bufferOffset是大于给定的缓冲区的长度,该方法将无用,委托将不会被调用
  589.               如果你传递一个缓冲区,当AsyncSocket在使用它的时候你不能以任何方式改变它
  590.               完成之后,onSocket:didReadData:withTag 返回的数据将是一个给定的缓冲区的子集
  591.               也就是说,它将会被引用到被追加的给定的缓冲区的字节

  592.             -(void)readDataToLength:(NSUInterger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  593.             读取给定的字节数,如果length为0,方法将无用,委托将不会被调用

  594.             -(void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)tiemout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;
  595.             读取给定的字节数,在给定的偏移开始,字节将被追加到给定的字节缓冲区

  596.             -(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  597.             读取字节直到(包括)传入的作为分隔的"data"参数
  598.             如果传递0或者0长度的数据,"data"参数,该方法将无用,委托将不会被调用
  599.             从socket读取一行,使用"data"参数作为行的分隔符 (如HTTP的CRLF)
  600.             注意,此方法不是字符集,因此,如果一个分隔符出现,它自然可以作为进行编码的一部分,读取将提前结束

  601.             -(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;
  602.            读取字节直到(包括)传入的作为分隔的“data”参数,在给定的偏移量开始,字节将被追加到给定的字节缓冲区。
  603.            从socket读取一行,使用"data"参数作为行的分隔符(如HTTP的CRLF)

  604.            -(void)writeData:(NSData *)data withTimeout:(NSTimeInterval) timeout tag:(long)tag;
  605.           将data写入socket,当完成的时候委托被调用 

  606.            - (float)progressOfReadReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;
  607.            - (float)progressOfWriteReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;
  608.            返回当前读或写的进度,从0.0 到 1.0 或者 如果没有读/写的时候返回Nan(使用isNan来检查)
  609.    tag、done、total如果不为空的话,它们将会被填补

  610.            

  611.            - (void)startTLS:(NSDictionary *)tlsSettings;
  612.            确保使用ssl/tls连接
  613.            这方法可被随时调用,tls握手将会发生在所有悬而未决的读/写完成之后。这紧跟着一个发送依赖 StartTLS消息的协议选项,在排队升级到TLS的同一时间,而不必等待写入完成。在这个方法被调用后,任何读写计划 将会发生在安全链接
  614.            对于可能的keys和TLS设置的值是有据可查的
  615.            一些可能的keys是:
  616.               * - kCFStreamSSLLevel
  617.               * - kCFStreamSSLAllowsExpiredCertificates
  618.               * - kCFStreamSSLAllowsExpiredRoots
  619.               * - kCFStreamSSLAllowsAnyRoot
  620.               * - kCFStreamSSLValidatesCertificateChain
  621.               * - kCFStreamSSLPeerName
  622.               * - kCFStreamSSLCertificates
  623.               * - kCFStreamSSLIsServer

  624.            如果你传递空或者空字典,将使用默认的字典
  625.            默认设置将检查以确保由签署可信的第三方证书机构和没有过期的远程连接的证书
  626.            然而,它不会验证证书上的名字,除非你给它一个名字,通过kCFStreamSSLPeerName键去验证
  627.            这对安全的影响是重要的理解
  628.            想象一下你正试图创建一个到MySecureServer.com的安全连接,但因为一个被攻击的DNS服务器,所以你的socket被定向到MaliciousServer.com
  629.            如果你只是使用默认设置,MaliciousServer.com 有一个有效的证书
  630.            默认设置将无法监测到任何问题,因为证书是有效的
  631.           在这个特殊的情况下,要妥善保护你的连接,应设置kCFStreamSSLPeerName性质为MySecureServer.com.
  632.          如果事前你不知道对等的名字的远程主机(例如,你不确认它是domain.com" or "www.domain.com"),那么你可以使用默认设置来验证证书,然后在获得验证的发行后使用X509Certificate类来验证,X509Certificate类的CocoaAsyncSocket开源项目的一部分

  633.          -(void)enablePrebuffering
  634.          对于处理readDataToData请求,数据是必须从socket以小增量的方式读取出来的
  635.          性能通过允许AsyncSocket去一次性读大块的数据和存储任何一个小的内部缓冲区溢出的东西来大大提高
  636.          这被称为预缓冲,就好像一些数据在你要求它之前就可能被读取出来
  637.          如果你经常使用readDataToData,使用预缓冲会有更好的性能,尤其是在iphone上
  638.          默认的预缓冲状态是由DEFAULT_PREBUFFERING 定义控制的,强烈建议设置其为yes
  639.          这方法存在一些预缓冲需要一些不可预见的原因被默认禁用的情况,这时,这种方法存在允许当就绪时,可轻松启用预缓冲

  640.           -(BOOL)moveToRunLoop:(NSRunLoop *)runLoop;
  641.           当你创建一个AsyncSocket,它被添加到当前线程runloop
  642.           对于手动创建的socket,在线程上你打算使用它,它是最容易简单的创建的线程上的socket
  643.           当一个新的socket被接受,委托方法 onSocket:wantsRunLoopForNewSocket 会被调用 允许你在一个单独的线程上放置socket,这个工作最好结合在同一个线程池设计
  644.           如果,但是,在一个单独的线程上,在之后的时间,你需要移动一个socket,这个方法可以用来完成任务
  645.           此方法必须从 当前运行的 线程/runloop 的socket 调用
  646.           注意:此方法调用后,所有进一步的方法应该从给定的runloop上调用这个对象
  647.           此外,所有委托调用将会发送到给定的runloop


  648.           - (BOOL)setRunLoopModes:(NSArray *)runLoopModes;
  649.           - (BOOL)addRunLoopMode:(NSString *)runLoopMode;
  650.           - (BOOL)removeRunLoopMode:(NSString *)runLoopMode;
  651.            允许你配置 socket 使用的 运行循环模式
  652.            运行循环模式设置默认是NSRunLoopCommonModes
  653.            如果你想你的socket 在其他模式下继续操作,你可能需要添加模式 NSModalPanelRunLoopMode 或者 NSEventTrackingRunLoopMode ,或者你可能只想使用 NSRunLoopCommonModes
  654.            可接受的socket将自动 继承相同的运行循环模式就像侦听socket
  655.            注意:NSRunLoopCommonModes 定义在10.5,对于之前的版本可使用 kCFRunLoopCommonModes

  656.           -(NSArray *)runLoopModes
  657.             返回当前正在运行的循环模式的AsyncSocket实例, run loop modes的默认设置是NSDefaultRunLoopMode

  658.           -(NSData *)unreadData;
  659.          一个错误的事件,在 onSocket:willDisconnectWithError: 将会被调用 去读取留在socket上的任何数据

  660.           + (NSData *)CRLFData;   // 0x0D0A
  661.   
  662. 各方法的解析
  663.        -(void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err;   
  664.        发生错误,socket关闭,可以在call-back过程调用"unreadData"去取得socket的最后的数据字节,当连接的时候,该委托方法在    onSocket:didAcceptNewSocket: 或者 onSocket:didConnectToHost: 之前调用

  665.       -(void)onSocketDidDisconnect:(ASyncSocket *)sock;
  666.       当socket由于或没有错误而断开连接,如果你想要在断开连接后release socket,在此方法工作,而在onSocket:willDisconnectWithError 释放则不安全

  667.        -(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket;
  668.         当产生一个socket去处理连接时调用,此方法会返回 线程上的run-loop 的新的socket和其应处理的委托,如果省略,则使用[NSRunLoop cunrrentRunLoop]

  669.           -(BOOL)onSocketWillConnect:(AsyncSocket *)sock;

  670.        -(void)onSocket:(AsyncSocket *)sock didConnectToHost :(NSString *)host port:(UINt16)port;
  671.           当socket连接正准备读和写的时候调用,host属性是一个IP地址,而不是一个DNS 名称

  672.          -(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long) tag;
  673.          当socket已完成所要求的数据读入内存时调用,如果有错误则不调用

  674.          -(void)onSocket:(Asyncsocket *)sock didReadPartialDataOfLength:(NSUInteger)partiaLength tag:(long)tag;
  675.            当一个socket读取数据,但尚未完成读操作的时候调用,如果使用 readToData: or readToLength: 方法 会发生,可以被用来更新进度条等东西

  676.             -(void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag;
  677.              当一个socket已完成请求数据的写入时候调用

  678.             -(void)onSocket:(AsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag;
  679.              当一个socket写入一些数据,但还没有完成整个写入时调用,它可以用来更新进度条等东西

  680.                -(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag elapsed:(NSTimeInterval)exapsed bytesDone:(NSUInteger)length
  681.               使用读操作已超时但还没完成时调用,此方法允许随意延迟超时,如果返回一个正的时间间隔,读取的超时将有一定量的扩展,如果不实现这个方法,或会像往常一样返回一个负的时间间隔,elapsed参数是  原超时的总和,加上先前通过这种方法添加的任何补充, length参数是 读操作到目前为止已读取的字节数, 注意,如果返回正数的话,这个方法可能被一个单独的读取多次调用

  682.                -(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutWriteWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length;
  683.                 如果一个写操作已达到其超时但还没完成时调用,同上

  684.                -(void)onSocketDidSecure:(AsyncSocket *)sock;
  685.                在socket成功完成ssl/tls协商时调用,此方法除非你使用提供startTLS方法时候才调用,
  686.     如果ssl/tls是无效的证书,socket将会立即关闭,onSocket:willDisconnectWithError:代理方法竟会与特定的ssl错误代码一起调用

  687.                -(BOOL)canSafelySetDelegate
  688.                用来查看在改变它之前,是否带有与当前的委托有悬而未决的业务(读/写)。当然,应在安全连接或接受委托之前改变委托

  689.               一旦接收或连接方法之一被调用,AsyncSocket实例会被锁定,其他接收/连接方法在没有先断开socket不会被调用
  690.               如果尝试失败或超时,这些方法要么返回NO 要么调用 onSocket:willDisconnectWithError: 或 onSockedDidDisconnect
  691.               当传入的连接被接受,AsyncSocket调用多个委托方法。这些方法按照时间顺序排列:
  692.                  1.onSocket:didAcceptNewSocket:
  693.                  2.onSocket:wantsRunLoopForNewSocket:
  694.                  3. onSocketWillConnect:
  695.                
  696.               你的服务器的代码将需要保留公认的socket(如果要接受它),最好的地方是要做到这一点可能在onSocket:didAcceptNewSocket:方法    
  697.              在读和写流已经为新接受的socket设置,onSocket:didConnectToHost:port 方法将在适当的运行循环调用
  698.              多线程注意,如果要想通过实施onSocket:wantsRunLoopForNewSocket:,移动另一个新接受的socket去到另一个循环的socket。然后,应该在调用读和写或者startTLS方法前,等待直到onSocket:didConnectToHost:port:方法。否则读和写时间原定于不正确的runloop,混乱可能会随之而来


  699.              -(BOOL)acceptOnPort:(UInit16)port error:(NSError **)errPtr;
  700.              告诉socket开始听取和接受制定端口上的连接,当一个连接到来的时候,AsyncSocket实例将调用各种委托方法,socket将听取所有可用的接口(wifi,以太网等)

  701.              -(BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error :(NSError **)errPtr;
  702.              连接给定的主机和端口,主机hostname可以是域名或者是Ip地址

  703.              -(BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError *)errPtr;
  704.              连接到一个给定的地址,制定一个sockaddr结构包裹住一个NSData对象,例如,NSData对象从NSNetService的地址方法返回,如果有一个现有的sockaddr结构,可以将它转换到一个NSData对象,像这样:
  705.  struct sockaddr sa  -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len];
  706.  struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len];

  707.              -(void)disconnect;
  708.                 立即断开,任何未处理的读或写都将被丢弃
  709.                 如果socket还没有断开,在这个方法返回之前,onSocketDidDisconnect 委托方法将会被立即调用
  710.                  注意推荐释放AsyncSocket实例的方式:
  711.                    [asyncSocket setDelegate:nil];
  712.                    [asyncSocket disconnect];
  713.                    [asyncSocket release];

  714.               -(void)disconnectAfterReading;
  715.                  在已经完成了所有悬而未决的读取时 断开,在调用之后,读取和写入方法将无用,socket将断开 即使仍有待写入

  716.               - (NSString *)connectedHost;
  717.               - (UInt16)connectedPort;
  718.               - (NSString *)localHost;
  719.               - (UInt16)localPort;
  720.                 返回本地和远程主机和端口给连接的socket,如果没有连接会返回nil或0,主机将会是一个IP地址

  721.              -(NSData *)connectedAddress
  722.              -(NSData *)localAddresss
  723.                 返回本地和远程的地址给连接的socket,指定一个socketaddr结构包裹在一个NSData对象


  724.                 readData和writeData方法不会是block(它们是异步的)
  725.                当读完成 onSocket:didReadData:withTag: 委托方法时调用
  726.                当写完成 onSocket:didWriteDataWithTag: 委托方法时调用
  727.                可以选择任何读/写操作的超时设置(为了不超时,使用负时间间隔。)
  728.                如果读/写操作超时,相应的 onSocket:shouldTimeout...委托方法被调用去选择性地允许我们去延长超时
  729.                超时后,onSocket:willDisconnectWithError: 方法被调用,紧接着是 onSocketDidDisconnect
  730.                tag是为了方便,可以使用它作为数组的索引、步数、state id 、指针等 



  731.             -(void)readDataWithTimeout:(NSTimeInterval)tiemout tag:(long)tag;
  732.               读取socket上第一次成为可用的字节,如果timeout值是负数的,读操作将不使用timeout

  733.             - (void)readDataWithTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInterger)offset tag:(long)tag;
  734.               读取socket上第一次成为可用的字节
  735.               字节将被追加到给定的字节缓冲区,从给定的偏移量开始
  736.               如果需要,给定的缓冲区大小将会自动增加
  737.               如果timeout值是负数的,读操作将不使用timeout
  738.               如果缓冲区为空,socket会为我们创建一个缓冲区
  739.               如果bufferOffset是大于给定的缓冲区的长度,该方法将无用,委托将不会被调用
  740.               如果你传递一个缓冲区,当AsyncSocket在使用它的时候你不能以任何方式改变它
  741.               完成之后,onSocket:didReadData:withTag 返回的数据将是一个给定的缓冲区的子集
  742.               也就是说,它将会被引用到被追加的给定的缓冲区的字节

  743.             -(void)readDataToLength:(NSUInterger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  744.             读取给定的字节数,如果length为0,方法将无用,委托将不会被调用

  745.             -(void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)tiemout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;
  746.             读取给定的字节数,在给定的偏移开始,字节将被追加到给定的字节缓冲区

  747.             -(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  748.             读取字节直到(包括)传入的作为分隔的"data"参数
  749.             如果传递0或者0长度的数据,"data"参数,该方法将无用,委托将不会被调用
  750.             从socket读取一行,使用"data"参数作为行的分隔符 (如HTTP的CRLF)
  751.             注意,此方法不是字符集,因此,如果一个分隔符出现,它自然可以作为进行编码的一部分,读取将提前结束

  752.             -(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;
  753.            读取字节直到(包括)传入的作为分隔的“data”参数,在给定的偏移量开始,字节将被追加到给定的字节缓冲区。
  754.            从socket读取一行,使用"data"参数作为行的分隔符(如HTTP的CRLF)

  755.            -(void)writeData:(NSData *)data withTimeout:(NSTimeInterval) timeout tag:(long)tag;
  756.           将data写入socket,当完成的时候委托被调用 

  757.            - (float)progressOfReadReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;
  758.            - (float)progressOfWriteReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;
  759.            返回当前读或写的进度,从0.0 到 1.0 或者 如果没有读/写的时候返回Nan(使用isNan来检查)
  760.    tag、done、total如果不为空的话,它们将会被填补

  761.            

  762.            - (void)startTLS:(NSDictionary *)tlsSettings;
  763.            确保使用ssl/tls连接
  764.            这方法可被随时调用,tls握手将会发生在所有悬而未决的读/写完成之后。这紧跟着一个发送依赖 StartTLS消息的协议选项,在排队升级到TLS的同一时间,而不必等待写入完成。在这个方法被调用后,任何读写计划 将会发生在安全链接
  765.            对于可能的keys和TLS设置的值是有据可查的
  766.            一些可能的keys是:
  767.               * - kCFStreamSSLLevel
  768.               * - kCFStreamSSLAllowsExpiredCertificates
  769.               * - kCFStreamSSLAllowsExpiredRoots
  770.               * - kCFStreamSSLAllowsAnyRoot
  771.               * - kCFStreamSSLValidatesCertificateChain
  772.               * - kCFStreamSSLPeerName
  773.               * - kCFStreamSSLCertificates
  774.               * - kCFStreamSSLIsServer

  775.            如果你传递空或者空字典,将使用默认的字典
  776.            默认设置将检查以确保由签署可信的第三方证书机构和没有过期的远程连接的证书
  777.            然而,它不会验证证书上的名字,除非你给它一个名字,通过kCFStreamSSLPeerName键去验证
  778.            这对安全的影响是重要的理解
  779.            想象一下你正试图创建一个到MySecureServer.com的安全连接,但因为一个被攻击的DNS服务器,所以你的socket被定向到MaliciousServer.com
  780.            如果你只是使用默认设置,MaliciousServer.com 有一个有效的证书
  781.            默认设置将无法监测到任何问题,因为证书是有效的
  782.           在这个特殊的情况下,要妥善保护你的连接,应设置kCFStreamSSLPeerName性质为MySecureServer.com.
  783.          如果事前你不知道对等的名字的远程主机(例如,你不确认它是domain.com" or "www.domain.com"),那么你可以使用默认设置来验证证书,然后在获得验证的发行后使用X509Certificate类来验证,X509Certificate类的CocoaAsyncSocket开源项目的一部分

  784.          -(void)enablePrebuffering
  785.          对于处理readDataToData请求,数据是必须从socket以小增量的方式读取出来的
  786.          性能通过允许AsyncSocket去一次性读大块的数据和存储任何一个小的内部缓冲区溢出的东西来大大提高
  787.          这被称为预缓冲,就好像一些数据在你要求它之前就可能被读取出来
  788.          如果你经常使用readDataToData,使用预缓冲会有更好的性能,尤其是在iphone上
  789.          默认的预缓冲状态是由DEFAULT_PREBUFFERING 定义控制的,强烈建议设置其为yes
  790.          这方法存在一些预缓冲需要一些不可预见的原因被默认禁用的情况,这时,这种方法存在允许当就绪时,可轻松启用预缓冲

  791.           -(BOOL)moveToRunLoop:(NSRunLoop *)runLoop;
  792.           当你创建一个AsyncSocket,它被添加到当前线程runloop
  793.           对于手动创建的socket,在线程上你打算使用它,它是最容易简单的创建的线程上的socket
  794.           当一个新的socket被接受,委托方法 onSocket:wantsRunLoopForNewSocket 会被调用 允许你在一个单独的线程上放置socket,这个工作最好结合在同一个线程池设计
  795.           如果,但是,在一个单独的线程上,在之后的时间,你需要移动一个socket,这个方法可以用来完成任务
  796.           此方法必须从 当前运行的 线程/runloop 的socket 调用
  797.           注意:此方法调用后,所有进一步的方法应该从给定的runloop上调用这个对象
  798.           此外,所有委托调用将会发送到给定的runloop


  799.           - (BOOL)setRunLoopModes:(NSArray *)runLoopModes;
  800.           - (BOOL)addRunLoopMode:(NSString *)runLoopMode;
  801.           - (BOOL)removeRunLoopMode:(NSString *)runLoopMode;
  802.            允许你配置 socket 使用的 运行循环模式
  803.            运行循环模式设置默认是NSRunLoopCommonModes
  804.            如果你想你的socket 在其他模式下继续操作,你可能需要添加模式 NSModalPanelRunLoopMode 或者 NSEventTrackingRunLoopMode ,或者你可能只想使用 NSRunLoopCommonModes
  805.            可接受的socket将自动 继承相同的运行循环模式就像侦听socket
  806.            注意:NSRunLoopCommonModes 定义在10.5,对于之前的版本可使用 kCFRunLoopCommonModes

  807.           -(NSArray *)runLoopModes
  808.             返回当前正在运行的循环模式的AsyncSocket实例, run loop modes的默认设置是NSDefaultRunLoopMode

  809.           -(NSData *)unreadData;
  810.          一个错误的事件,在 onSocket:willDisconnectWithError: 将会被调用 去读取留在socket上的任何数据

  811.           + (NSData *)CRLFData;   // 0x0D0A
  812.   
  813. 各方法的解析
  814.        -(void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err;   
  815.        发生错误,socket关闭,可以在call-back过程调用"unreadData"去取得socket的最后的数据字节,当连接的时候,该委托方法在    onSocket:didAcceptNewSocket: 或者 onSocket:didConnectToHost: 之前调用
  816.        发生错误,socket关闭,可以在call-back过程调用"unreadData"去取得socket的最后的数据字节,当连接的时候,该委托方法在    onSocket:didAcceptNewSocket: 或者 onSocket:didConnectToHost: 之前调用
  817.       -(void)onSocketDidDisconnect:(ASyncSocket *)sock;
  818.       当socket由于或没有错误而断开连接,如果你想要在断开连接后release socket,在此方法工作,而在onSocket:willDisconnectWithError 释放则不安全
  819.        -(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket;
  820.         当产生一个socket去处理连接时调用,此方法会返回 线程上的run-loop 的新的socket和其应处理的委托,如果省略,则使用[NSRunLoop cunrrentRunLoop]
  821.         当产生一个socket去处理连接时调用,此方法会返回 线程上的run-loop 的新的socket和其应处理的委托,如果省略,则使用[NSRunLoop cunrrentRunLoop]
  822.           -(BOOL)onSocketWillConnect:(AsyncSocket *)sock;
  823.        -(void)onSocket:(AsyncSocket *)sock didConnectToHost :(NSString *)host port:(UINt16)port;
  824.           当socket连接正准备读和写的时候调用,host属性是一个IP地址,而不是一个DNS 名称
  825.          -(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long) tag;
  826.          当socket已完成所要求的数据读入内存时调用,如果有错误则不调用
  827.          -(void)onSocket:(Asyncsocket *)sock didReadPartialDataOfLength:(NSUInteger)partiaLength tag:(long)tag;
  828.            当一个socket读取数据,但尚未完成读操作的时候调用,如果使用 readToData: or readToLength: 方法 会发生,可以被用来更新进度条等东西
  829.             -(void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag;
  830.              当一个socket已完成请求数据的写入时候调用
  831.             -(void)onSocket:(AsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag;
  832.              当一个socket写入一些数据,但还没有完成整个写入时调用,它可以用来更新进度条等东西
  833.                -(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag elapsed:(NSTimeInterval)exapsed bytesDone:(NSUInteger)length
  834.               使用读操作已超时但还没完成时调用,此方法允许随意延迟超时,如果返回一个正的时间间隔,读取的超时将有一定量的扩展,如果不实现这个方法,或会像往常一样返回一个负的时间间隔,elapsed参数是  原超时的总和,加上先前通过这种方法添加的任何补充, length参数是 读操作到目前为止已读取的字节数, 注意,如果返回正数的话,这个方法可能被一个单独的读取多次调用
  835.                -(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutWriteWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length;
  836.                 如果一个写操作已达到其超时但还没完成时调用,同上
  837.                -(void)onSocketDidSecure:(AsyncSocket *)sock;
  838.                在socket成功完成ssl/tls协商时调用,此方法除非你使用提供startTLS方法时候才调用,
  839.     如果ssl/tls是无效的证书,socket将会立即关闭,onSocket:willDisconnectWithError:代理方法竟会与特定的ssl错误代码一起调用
  840.                -(BOOL)canSafelySetDelegate
  841.                用来查看在改变它之前,是否带有与当前的委托有悬而未决的业务(读/写)。当然,应在安全连接或接受委托之前改变委托
  842.               一旦接收或连接方法之一被调用,AsyncSocket实例会被锁定,其他接收/连接方法在没有先断开socket不会被调用
  843.               如果尝试失败或超时,这些方法要么返回NO 要么调用 onSocket:willDisconnectWithError: 或 onSockedDidDisconnect
  844.               当传入的连接被接受,AsyncSocket调用多个委托方法。这些方法按照时间顺序排列:
  845.                  1.onSocket:didAcceptNewSocket:
  846.                  2.onSocket:wantsRunLoopForNewSocket:
  847.                  3. onSocketWillConnect:
  848.                
  849.               你的服务器的代码将需要保留公认的socket(如果要接受它),最好的地方是要做到这一点可能在onSocket:didAcceptNewSocket:方法    
  850.              在读和写流已经为新接受的socket设置,onSocket:didConnectToHost:port 方法将在适当的运行循环调用
  851.              多线程注意,如果要想通过实施onSocket:wantsRunLoopForNewSocket:,移动另一个新接受的socket去到另一个循环的socket。然后,应该在调用读和写或者startTLS方法前,等待直到onSocket:didConnectToHost:port:方法。否则读和写时间原定于不正确的runloop,混乱可能会随之而来

  852.              -(BOOL)acceptOnPort:(UInit16)port error:(NSError **)errPtr;
  853.              告诉socket开始听取和接受制定端口上的连接,当一个连接到来的时候,AsyncSocket实例将调用各种委托方法,socket将听取所有可用的接口(wifi,以太网等)
  854.              -(BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error :(NSError **)errPtr;
  855.              连接给定的主机和端口,主机hostname可以是域名或者是Ip地址
  856.              -(BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError *)errPtr;
  857.              连接到一个给定的地址,制定一个sockaddr结构包裹住一个NSData对象,例如,NSData对象从NSNetService的地址方法返回,如果有一个现有的sockaddr结构,可以将它转换到一个NSData对象,像这样:
  858.  struct sockaddr sa  -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len];
  859.  struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len];
  860.              -(void)disconnect;
  861.                 立即断开,任何未处理的读或写都将被丢弃
  862.                 如果socket还没有断开,在这个方法返回之前,onSocketDidDisconnect 委托方法将会被立即调用
  863.                  注意推荐释放AsyncSocket实例的方式:
  864.                    [asyncSocket setDelegate:nil];
  865.                    [asyncSocket disconnect];
  866.                    [asyncSocket release];
  867.               -(void)disconnectAfterReading;
  868.                  在已经完成了所有悬而未决的读取时 断开,在调用之后,读取和写入方法将无用,socket将断开 即使仍有待写入
  869.               - (NSString *)connectedHost;
  870.               - (UInt16)connectedPort;
  871.               - (NSString *)localHost;
  872.               - (UInt16)localPort;
  873.                 返回本地和远程主机和端口给连接的socket,如果没有连接会返回nil或0,主机将会是一个IP地址
  874.              -(NSData *)connectedAddress
  875.              -(NSData *)localAddresss
  876.                 返回本地和远程的地址给连接的socket,指定一个socketaddr结构包裹在一个NSData对象

  877.                 readData和writeData方法不会是block(它们是异步的)
  878.                当读完成 onSocket:didReadData:withTag: 委托方法时调用
  879.                当写完成 onSocket:didWriteDataWithTag: 委托方法时调用
  880.                可以选择任何读/写操作的超时设置(为了不超时,使用负时间间隔。)
  881.                如果读/写操作超时,相应的 onSocket:shouldTimeout...委托方法被调用去选择性地允许我们去延长超时
  882.                超时后,onSocket:willDisconnectWithError: 方法被调用,紧接着是 onSocketDidDisconnect
  883.                tag是为了方便,可以使用它作为数组的索引、步数、state id 、指针等 


  884.             -(void)readDataWithTimeout:(NSTimeInterval)tiemout tag:(long)tag;
  885.               读取socket上第一次成为可用的字节,如果timeout值是负数的,读操作将不使用timeout
  886.             - (void)readDataWithTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInterger)offset tag:(long)tag;
  887.               读取socket上第一次成为可用的字节
  888.               字节将被追加到给定的字节缓冲区,从给定的偏移量开始
  889.               如果需要,给定的缓冲区大小将会自动增加
  890.               如果timeout值是负数的,读操作将不使用timeout
  891.               如果缓冲区为空,socket会为我们创建一个缓冲区
  892.               如果bufferOffset是大于给定的缓冲区的长度,该方法将无用,委托将不会被调用
  893.               如果你传递一个缓冲区,当AsyncSocket在使用它的时候你不能以任何方式改变它
  894.               完成之后,onSocket:didReadData:withTag 返回的数据将是一个给定的缓冲区的子集
  895.               也就是说,它将会被引用到被追加的给定的缓冲区的字节
  896.             -(void)readDataToLength:(NSUInterger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  897.             读取给定的字节数,如果length为0,方法将无用,委托将不会被调用
  898.             -(void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)tiemout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;
  899.             读取给定的字节数,在给定的偏移开始,字节将被追加到给定的字节缓冲区
  900.             -(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  901.             读取字节直到(包括)传入的作为分隔的"data"参数
  902.             如果传递0或者0长度的数据,"data"参数,该方法将无用,委托将不会被调用
  903.             从socket读取一行,使用"data"参数作为行的分隔符 (如HTTP的CRLF)
  904.             注意,此方法不是字符集,因此,如果一个分隔符出现,它自然可以作为进行编码的一部分,读取将提前结束
  905.             -(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;
  906.            读取字节直到(包括)传入的作为分隔的“data”参数,在给定的偏移量开始,字节将被追加到给定的字节缓冲区。
  907.            从socket读取一行,使用"data"参数作为行的分隔符(如HTTP的CRLF)
  908.            -(void)writeData:(NSData *)data withTimeout:(NSTimeInterval) timeout tag:(long)tag;
  909.           将data写入socket,当完成的时候委托被调用 
  910.            - (float)progressOfReadReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;
  911.            - (float)progressOfWriteReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;
  912.            返回当前读或写的进度,从0.0 到 1.0 或者 如果没有读/写的时候返回Nan(使用isNan来检查)
  913.    tag、done、total如果不为空的话,它们将会被填补
  914.            
  915.            - (void)startTLS:(NSDictionary *)tlsSettings;
  916.            确保使用ssl/tls连接
  917.            这方法可被随时调用,tls握手将会发生在所有悬而未决的读/写完成之后。这紧跟着一个发送依赖 StartTLS消息的协议选项,在排队升级到TLS的同一时间,而不必等待写入完成。在这个方法被调用后,任何读写计划 将会发生在安全链接
  918.            对于可能的keys和TLS设置的值是有据可查的
  919.            一些可能的keys是:
  920.               * - kCFStreamSSLLevel
  921.               * - kCFStreamSSLAllowsExpiredCertificates
  922.               * - kCFStreamSSLAllowsExpiredRoots
  923.               * - kCFStreamSSLAllowsAnyRoot
  924.               * - kCFStreamSSLValidatesCertificateChain
  925.               * - kCFStreamSSLPeerName
  926.               * - kCFStreamSSLCertificates
  927.               * - kCFStreamSSLIsServer
  928.            如果你传递空或者空字典,将使用默认的字典
  929.            默认设置将检查以确保由签署可信的第三方证书机构和没有过期的远程连接的证书
  930.            然而,它不会验证证书上的名字,除非你给它一个名字,通过kCFStreamSSLPeerName键去验证
  931.            这对安全的影响是重要的理解
  932.            想象一下你正试图创建一个到MySecureServer.com的安全连接,但因为一个被攻击的DNS服务器,所以你的socket被定向到MaliciousServer.com
  933.            如果你只是使用默认设置,MaliciousServer.com 有一个有效的证书
  934.            默认设置将无法监测到任何问题,因为证书是有效的
  935.           在这个特殊的情况下,要妥善保护你的连接,应设置kCFStreamSSLPeerName性质为MySecureServer.com.
  936.          如果事前你不知道对等的名字的远程主机(例如,你不确认它是domain.com" or "www.domain.com"),那么你可以使用默认设置来验证证书,然后在获得验证的发行后使用X509Certificate类来验证,X509Certificate类的CocoaAsyncSocket开源项目的一部分
  937.          -(void)enablePrebuffering
  938.          对于处理readDataToData请求,数据是必须从socket以小增量的方式读取出来的
  939.          性能通过允许AsyncSocket去一次性读大块的数据和存储任何一个小的内部缓冲区溢出的东西来大大提高
  940.          这被称为预缓冲,就好像一些数据在你要求它之前就可能被读取出来
  941.          如果你经常使用readDataToData,使用预缓冲会有更好的性能,尤其是在iphone上
  942.          默认的预缓冲状态是由DEFAULT_PREBUFFERING 定义控制的,强烈建议设置其为yes
  943.          这方法存在一些预缓冲需要一些不可预见的原因被默认禁用的情况,这时,这种方法存在允许当就绪时,可轻松启用预缓冲
  944.           -(BOOL)moveToRunLoop:(NSRunLoop *)runLoop;
  945.           当你创建一个AsyncSocket,它被添加到当前线程runloop
  946.           对于手动创建的socket,在线程上你打算使用它,它是最容易简单的创建的线程上的socket
  947.           当一个新的socket被接受,委托方法 onSocket:wantsRunLoopForNewSocket 会被调用 允许你在一个单独的线程上放置socket,这个工作最好结合在同一个线程池设计
  948.           如果,但是,在一个单独的线程上,在之后的时间,你需要移动一个socket,这个方法可以用来完成任务
  949.           此方法必须从 当前运行的 线程/runloop 的socket 调用
  950.           注意:此方法调用后,所有进一步的方法应该从给定的runloop上调用这个对象
  951.           此外,所有委托调用将会发送到给定的runloop

  952.           - (BOOL)setRunLoopModes:(NSArray *)runLoopModes;
  953.           - (BOOL)addRunLoopMode:(NSString *)runLoopMode;
  954.           - (BOOL)removeRunLoopMode:(NSString *)runLoopMode;
  955.            允许你配置 socket 使用的 运行循环模式
  956.            运行循环模式设置默认是NSRunLoopCommonModes
  957.            如果你想你的socket 在其他模式下继续操作,你可能需要添加模式 NSModalPanelRunLoopMode 或者 NSEventTrackingRunLoopMode ,或者你可能只想使用 NSRunLoopCommonModes
  958.            可接受的socket将自动 继承相同的运行循环模式就像侦听socket
  959.            注意:NSRunLoopCommonModes 定义在10.5,对于之前的版本可使用 kCFRunLoopCommonModes
  960.           -(NSArray *)runLoopModes
  961.             返回当前正在运行的循环模式的AsyncSocket实例, run loop modes的默认设置是NSDefaultRunLoopMode
  962.           -(NSData *)unreadData;
  963.          一个错误的事件,在 onSocket:willDisconnectWithError: 将会被调用 去读取留在socket上的任何数据
  964.           + (NSData *)CRLFData;   // 0x0D0A
  965.   
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值