AsyncSocket API簡述

iPhone的標準推薦是CFNetwork 庫編程辩涝,其封裝好的開源庫是 cocoa AsyncSocket庫足陨,用它來簡化CFNetwork的調(diào)用,它提供了異步操作

主要特性有:

隊列的非阻塞的讀和寫,而且可選超時。你可以調(diào)用它讀取和寫入毅贮,它會當完成后告知你

自動的socket接收。如果你調(diào)用它接收連接尘奏,它將為每個連接啟動新的實例滩褥,當然,也可以立即關(guān)閉這些連接

委托(delegate)支持炫加。錯誤瑰煎、連接、接收琢感、完整的讀取丢间、完整的寫入探熔、進度以及斷開連接驹针,都可以通過委托模式調(diào)用

基于run loop的,而不是線程的诀艰。雖然可以在主線程或者工作線程中使用它柬甥,但你不需要這樣做饮六。它異步的調(diào)用委托方法,使用NSRunLoop苛蒲。委托方法包括socket的參數(shù)卤橄,可讓你在多個實例中區(qū)分

自包含在一個類中。你無需操作流或者socket臂外,這個類幫你做了全部

支持基于IPV4和IPV6的TCP流

加入:AsynSocket.h .m與AsynUdpSocket.h .m四個文件 及CFNetwork.framework

TCP客戶端

#import "AsyncSocket.h"

@interface HelloiPhoneViewController : UIViewController {

UITextField ? ?* textField;

AsyncSocket * asyncSocket;

}

@property (retain, nonatomic) IBOutlet UITextField *textField;

- (IBAction) buttonPressed: (id)sender;

- (IBAction) textFieldDoneEditing: (id)sender;

@end

在需要聯(lián)接地方使用connectToHost聯(lián)接服務(wù)器

其中initWithDelegate的參數(shù)中self是必須窟扑。這個對象指針中的各個Socket響應(yīng)的函數(shù)將被ASyncSocket所調(diào)用.initWithDelegate把將當前對象傳遞進去,這樣只要在當前對象方法實現(xiàn)相應(yīng)方法

asyncSocket = [[AsyncSocket alloc] initWithDelegate:self];

NSError *err = nil;

if(![asyncSocket connectToHost:host on:port error:&err])

{

NSLog(@"Error: %@", err);

}

關(guān)于NSData對象

無論SOCKET收發(fā)都采用NSData對象.它的定義是?http://developer.apple.com/library/mac /#documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/Reference/Reference.html

NSData主要是帶一個(id)data指向的數(shù)據(jù)空間和長度 length.

NSString 轉(zhuǎn)換成NSData 對象

NSData* xmlData = [@"testdata" dataUsingEncoding:NSUTF8StringEncoding];

NSData 轉(zhuǎn)換成NSString對象

NSData * data;

NSString *result = [[NSString alloc] initWithData:data ??????? encoding:NSUTF8StringEncoding];

發(fā)送數(shù)據(jù)

AsyncSocket ?writeData ? ?方法來發(fā)送數(shù)據(jù)漏健,它有如下定義

- (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;

以下是一個實例語句.

NSData* aData= [@"test data" dataUsingEncoding: NSUTF8StringEncoding];

[sock writeData:aData withTimeout:-1 tag:1];

在onSocket重載函數(shù)嚎货,有如定義采用是專門用來處理SOCKET的發(fā)送數(shù)據(jù)的:

-(void)onSocket(AsyncSocket *)sock didWriteDataWithTag:(long)tag

{

NSLog(@"thread(%),onSocket:%p didWriteDataWithTag:%d",[[NSThread currentThread] name],

sock,tag);

}

接收Socket數(shù)據(jù).

在onSocket重載函數(shù),有如定義采用是專門用來處理SOCKET的接收數(shù)據(jù)的.

-(void) onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag

在中間將其轉(zhuǎn)換成NSString進行顯示.

NSString* aStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

NSLog(@"===%@",aStr);

[aStr release];

6蔫浆、TCP連接讀取制定長度的數(shù)據(jù)

socket連接,可能會讀取固定長度的字節(jié)

[socket readDataToLength: withTimeout :tag]

各方法的解析

-(void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err;

發(fā)生錯誤,socket關(guān)閉铺董,可以在call-back過程調(diào)用"unreadData"去取得socket的最后的數(shù)據(jù)字節(jié)祸挪,當連接的時候,該委托方法在??? onSocket:didAcceptNewSocket: 或者 onSocket:didConnectToHost: 之前調(diào)用

-(void)onSocketDidDisconnect:(ASyncSocket *)sock;

當socket由于或沒有錯誤而斷開連接原环,如果你想要在斷開連接后release socket挠唆,在此方法工作,而在onSocket:willDisconnectWithError 釋放則不安全

-(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket;

當產(chǎn)生一個socket去處理連接時調(diào)用嘱吗,此方法會返回 線程上的run-loop 的新的socket和其應(yīng)處理的委托损搬,如果省略,則使用[NSRunLoop cunrrentRunLoop]

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

-(void)onSocket:(AsyncSocket *)sock didConnectToHost :(NSString *)host port:(UINt16)port;

當socket連接正準備讀和寫的時候調(diào)用柜与,host屬性是一個IP地址巧勤,而不是一個DNS 名稱

-(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long) tag;

當socket已完成所要求的數(shù)據(jù)讀入內(nèi)存時調(diào)用,如果有錯誤則不調(diào)用

-(void)onSocket:(Asyncsocket *)sock didReadPartialDataOfLength:(NSUInteger)partiaLength tag:(long)tag;

當一個socket讀取數(shù)據(jù)弄匕,但尚未完成讀操作的時候調(diào)用颅悉,如果使用 readToData: or readToLength: 方法 會發(fā)生,可以被用來更新進度條等東西

-(void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag;

當一個socket已完成請求數(shù)據(jù)的寫入時候調(diào)用

-(void)onSocket:(AsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag;

當一個socket寫入一些數(shù)據(jù),但還沒有完成整個寫入時調(diào)用迁匠,它可以用來更新進度條等東西

-(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag elapsed:(NSTimeInterval)exapsed bytesDone:(NSUInteger)length

使用讀操作已超時但還沒完成時調(diào)用剩瓶,此方法允許隨意延遲超時,如果返回一個正的時間間隔城丧,讀取的超時將有一定量的擴展延曙,如果不實現(xiàn)這個方法,或會像往常一樣返回一個負的時間間隔亡哄,elapsed參數(shù)是? 原超時的總和枝缔,加上先前通過這種方法添加的任何補充, length參數(shù)是 讀操作到目前為止已讀取的字節(jié)數(shù), 注意愿卸,如果返回正數(shù)的話灵临,這個方法可能被一個單獨的讀取多次調(diào)用

-(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutWriteWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length;

如果一個寫操作已達到其超時但還沒完成時調(diào)用,同上

-(void)onSocketDidSecure:(AsyncSocket *)sock;

在socket成功完成ssl/tls協(xié)商時調(diào)用趴荸,此方法除非你使用提供startTLS方法時候才調(diào)用儒溉,

如果ssl/tls是無效的證書,socket將會立即關(guān)閉发钝,onSocket:willDisconnectWithError:代理方法竟會與特定的ssl錯誤代碼一起調(diào)用

-(BOOL)canSafelySetDelegate

用來查看在改變它之前顿涣,是否帶有與當前的委托有懸而未決的業(yè)務(wù)(讀/寫)。當然酝豪,應(yīng)在安全連接或接受委托之前改變委托

一旦接收或連接方法之一被調(diào)用园骆,AsyncSocket實例會被鎖定,其他接收/連接方法在沒有先斷開socket不會被調(diào)用

如果嘗試失敗或超時寓调,這些方法要么返回NO 要么調(diào)用 onSocket:willDisconnectWithError: 或 onSockedDidDisconnect

當傳入的連接被接受晌涕,AsyncSocket調(diào)用多個委托方法。這些方法按照時間順序排列:

1.onSocket:didAcceptNewSocket:

2.onSocket:wantsRunLoopForNewSocket:

3. onSocketWillConnect:

你的服務(wù)器的代碼將需要保留公認的socket(如果要接受它)熊泵,最好的地方是要做到這一點可能在onSocket:didAcceptNewSocket:方法

在讀和寫流已經(jīng)為新接受的socket設(shè)置冰蘑,onSocket:didConnectToHost:port 方法將在適當?shù)倪\行循環(huán)調(diào)用

多線程注意忠烛,如果要想通過實施onSocket:wantsRunLoopForNewSocket:胯陋,移動另一個新接受的socket去到另一個循環(huán)的socket。然后缩滨,應(yīng)該在調(diào)用讀和寫或者startTLS方法前司忱,等待直到onSocket:didConnectToHost:port:方法皇忿。否則讀和寫時間原定于不正確的runloop,混亂可能會隨之而來

-(BOOL)acceptOnPort:(UInit16)port error:(NSError **)errPtr;

告訴socket開始聽取和接受制定端口上的連接坦仍,當一個連接到來的時候鳍烁,AsyncSocket實例將調(diào)用各種委托方法,socket將聽取所有可用的接口(wifi,以太網(wǎng)等)

-(BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error :(NSError **)errPtr;

連接給定的主機和端口繁扎,主機hostname可以是域名或者是Ip地址

-(BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError *)errPtr;

連接到一個給定的地址幔荒,制定一個sockaddr結(jié)構(gòu)包裹住一個NSData對象,例如,NSData對象從NSNetService的地址方法返回,如果有一個現(xiàn)有的sockaddr結(jié)構(gòu)梳玫,可以將它轉(zhuǎn)換到一個NSData對象爹梁,像這樣:

struct sockaddr sa? -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len];

struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len];

-(void)disconnect;

立即斷開,任何未處理的讀或?qū)懚紝⒈粊G棄

如果socket還沒有斷開汽纠,在這個方法返回之前卫键,onSocketDidDisconnect 委托方法將會被立即調(diào)用

注意推薦釋放AsyncSocket實例的方式:

[asyncSocket setDelegate:nil];

[asyncSocket disconnect];

[asyncSocket release];

-(void)disconnectAfterReading;

在已經(jīng)完成了所有懸而未決的讀取時 斷開,在調(diào)用之后,讀取和寫入方法將無用,socket將斷開 即使仍有待寫入

- (NSString *)connectedHost;

- (UInt16)connectedPort;

- (NSString *)localHost;

- (UInt16)localPort;

返回本地和遠程主機和端口給連接的socket虱朵,如果沒有連接會返回nil或0,主機將會是一個IP地址

-(NSData *)connectedAddress

-(NSData *)localAddresss

返回本地和遠程的地址給連接的socket莉炉,指定一個socketaddr結(jié)構(gòu)包裹在一個NSData對象

readData和writeData方法不會是block(它們是異步的)

當讀完成 onSocket:didReadData:withTag: 委托方法時調(diào)用

當寫完成 onSocket:didWriteDataWithTag: 委托方法時調(diào)用

可以選擇任何讀/寫操作的超時設(shè)置(為了不超時,使用負時間間隔碴犬。)

如果讀/寫操作超時絮宁,相應(yīng)的 onSocket:shouldTimeout...委托方法被調(diào)用去選擇性地允許我們?nèi)パ娱L超時

超時后,onSocket:willDisconnectWithError: 方法被調(diào)用,緊接著是 onSocketDidDisconnect

tag是為了方便服协,可以使用它作為數(shù)組的索引绍昂、步數(shù)、state id 偿荷、指針等

-(void)readDataWithTimeout:(NSTimeInterval)tiemout tag:(long)tag;

讀取socket上第一次成為可用的字節(jié),如果timeout值是負數(shù)的窘游,讀操作將不使用timeout

- (void)readDataWithTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInterger)offset tag:(long)tag;

讀取socket上第一次成為可用的字節(jié)

字節(jié)將被追加到給定的字節(jié)緩沖區(qū),從給定的偏移量開始

如果需要跳纳,給定的緩沖區(qū)大小將會自動增加

如果timeout值是負數(shù)的忍饰,讀操作將不使用timeout

如果緩沖區(qū)為空,socket會為我們創(chuàng)建一個緩沖區(qū)

如果bufferOffset是大于給定的緩沖區(qū)的長度寺庄,該方法將無用艾蓝,委托將不會被調(diào)用

如果你傳遞一個緩沖區(qū)力崇,當AsyncSocket在使用它的時候你不能以任何方式改變它

完成之后,onSocket:didReadData:withTag 返回的數(shù)據(jù)將是一個給定的緩沖區(qū)的子集

也就是說赢织,它將會被引用到被追加的給定的緩沖區(qū)的字節(jié)

-(void)readDataToLength:(NSUInterger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag;

讀取給定的字節(jié)數(shù)亮靴,如果length為0,方法將無用于置,委托將不會被調(diào)用

-(void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)tiemout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;

讀取給定的字節(jié)數(shù),在給定的偏移開始茧吊,字節(jié)將被追加到給定的字節(jié)緩沖區(qū)

-(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;

讀取字節(jié)直到(包括)傳入的作為分隔的"data"參數(shù)

如果傳遞0或者0長度的數(shù)據(jù),"data"參數(shù)俱两,該方法將無用饱狂,委托將不會被調(diào)用

從socket讀取一行曹步,使用"data"參數(shù)作為行的分隔符 (如HTTP的CRLF)

注意宪彩,此方法不是字符集,因此讲婚,如果一個分隔符出現(xiàn)尿孔,它自然可以作為進行編碼的一部分,讀取將提前結(jié)束

-(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;

讀取字節(jié)直到(包括)傳入的作為分隔的“data”參數(shù)筹麸,在給定的偏移量開始活合,字節(jié)將被追加到給定的字節(jié)緩沖區(qū)。

從socket讀取一行物赶,使用"data"參數(shù)作為行的分隔符(如HTTP的CRLF)

-(void)writeData:(NSData *)data withTimeout:(NSTimeInterval) timeout tag:(long)tag;

將data寫入socket白指,當完成的時候委托被調(diào)用

- (float)progressOfReadReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;

- (float)progressOfWriteReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;

返回當前讀或?qū)懙倪M度,從0.0 到 1.0 或者 如果沒有讀/寫的時候返回Nan(使用isNan來檢查)

tag酵紫、done告嘲、total如果不為空的話,它們將會被填補

- (void)startTLS:(NSDictionary *)tlsSettings;

確保使用ssl/tls連接

這方法可被隨時調(diào)用奖地,tls握手將會發(fā)生在所有懸而未決的讀/寫完成之后橄唬。這緊跟著一個發(fā)送依賴 StartTLS消息的協(xié)議選項,在排隊升級到TLS的同一時間参歹,而不必等待寫入完成仰楚。在這個方法被調(diào)用后,任何讀寫計劃 將會發(fā)生在安全鏈接

對于可能的keys和TLS設(shè)置的值是有據(jù)可查的

一些可能的keys是:

* - kCFStreamSSLLevel

* - kCFStreamSSLAllowsExpiredCertificates

* - kCFStreamSSLAllowsExpiredRoots

* - kCFStreamSSLAllowsAnyRoot

* - kCFStreamSSLValidatesCertificateChain

* - kCFStreamSSLPeerName

* - kCFStreamSSLCertificates

* - kCFStreamSSLIsServer

如果你傳遞空或者空字典,將使用默認的字典

默認設(shè)置將檢查以確保由簽署可信的第三方證書機構(gòu)和沒有過期的遠程連接的證書

然而犬庇,它不會驗證證書上的名字僧界,除非你給它一個名字,通過kCFStreamSSLPeerName鍵去驗證

這對安全的影響是重要的理解

想象一下你正試圖創(chuàng)建一個到MySecureServer.com的安全連接臭挽,但因為一個被攻擊的DNS服務(wù)器捂襟,所以你的socket被定向到MaliciousServer.com

如果你只是使用默認設(shè)置,MaliciousServer.com 有一個有效的證書

默認設(shè)置將無法監(jiān)測到任何問題埋哟,因為證書是有效的

在這個特殊的情況下笆豁,要妥善保護你的連接郎汪,應(yīng)設(shè)置kCFStreamSSLPeerName性質(zhì)為MySecureServer.com.

如果事前你不知道對等的名字的遠程主機(例如,你不確認它是domain.com" or "www.domain.com")闯狱,那么你可以使用默認設(shè)置來驗證證書煞赢,然后在獲得驗證的發(fā)行后使用X509Certificate類來驗證,X509Certificate類的CocoaAsyncSocket開源項目的一部分

-(void)enablePrebuffering

對于處理readDataToData請求,數(shù)據(jù)是必須從socket以小增量的方式讀取出來的

性能通過允許AsyncSocket去一次性讀大塊的數(shù)據(jù)和存儲任何一個小的內(nèi)部緩沖區(qū)溢出的東西來大大提高

這被稱為預(yù)緩沖哄孤,就好像一些數(shù)據(jù)在你要求它之前就可能被讀取出來

如果你經(jīng)常使用readDataToData照筑,使用預(yù)緩沖會有更好的性能,尤其是在iphone上

默認的預(yù)緩沖狀態(tài)是由DEFAULT_PREBUFFERING 定義控制的瘦陈,強烈建議設(shè)置其為yes

這方法存在一些預(yù)緩沖需要一些不可預(yù)見的原因被默認禁用的情況凝危,這時,這種方法存在允許當就緒時晨逝,可輕松啟用預(yù)緩沖

-(BOOL)moveToRunLoop:(NSRunLoop *)runLoop;

當你創(chuàng)建一個AsyncSocket蛾默,它被添加到當前線程runloop

對于手動創(chuàng)建的socket,在線程上你打算使用它捉貌,它是最容易簡單的創(chuàng)建的線程上的socket

當一個新的socket被接受支鸡,委托方法 onSocket:wantsRunLoopForNewSocket 會被調(diào)用 允許你在一個單獨的線程上放置socket,這個工作最好結(jié)合在同一個線程池設(shè)計

如果趁窃,但是牧挣,在一個單獨的線程上,在之后的時間醒陆,你需要移動一個socket瀑构,這個方法可以用來完成任務(wù)

此方法必須從 當前運行的 線程/runloop 的socket 調(diào)用

注意:此方法調(diào)用后,所有進一步的方法應(yīng)該從給定的runloop上調(diào)用這個對象

此外刨摩,所有委托調(diào)用將會發(fā)送到給定的runloop

- (BOOL)setRunLoopModes:(NSArray *)runLoopModes;

- (BOOL)addRunLoopMode:(NSString *)runLoopMode;

- (BOOL)removeRunLoopMode:(NSString *)runLoopMode;

允許你配置 socket 使用的 運行循環(huán)模式

運行循環(huán)模式設(shè)置默認是NSRunLoopCommonModes

如果你想你的socket 在其他模式下繼續(xù)操作寺晌,你可能需要添加模式 NSModalPanelRunLoopMode 或者 NSEventTrackingRunLoopMode ,或者你可能只想使用 NSRunLoopCommonModes

可接受的socket將自動 繼承相同的運行循環(huán)模式就像偵聽socket

注意:NSRunLoopCommonModes 定義在10.5,對于之前的版本可使用 kCFRunLoopCommonModes

-(NSArray *)runLoopModes

返回當前正在運行的循環(huán)模式的AsyncSocket實例码邻, run loop modes的默認設(shè)置是NSDefaultRunLoopMode

-(NSData *)unreadData;

一個錯誤的事件折剃,在 onSocket:willDisconnectWithError: 將會被調(diào)用 去讀取留在socket上的任何數(shù)據(jù)

+ (NSData *)CRLFData;?? // 0x0D0A

各方法的解析

-(void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err;

發(fā)生錯誤,socket關(guān)閉像屋,可以在call-back過程調(diào)用"unreadData"去取得socket的最后的數(shù)據(jù)字節(jié)怕犁,當連接的時候,該委托方法在??? onSocket:didAcceptNewSocket: 或者 onSocket:didConnectToHost: 之前調(diào)用

-(void)onSocketDidDisconnect:(ASyncSocket *)sock;

當socket由于或沒有錯誤而斷開連接己莺,如果你想要在斷開連接后release socket奏甫,在此方法工作,而在onSocket:willDisconnectWithError 釋放則不安全

-(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket;

當產(chǎn)生一個socket去處理連接時調(diào)用凌受,此方法會返回 線程上的run-loop 的新的socket和其應(yīng)處理的委托阵子,如果省略,則使用[NSRunLoop cunrrentRunLoop]

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

-(void)onSocket:(AsyncSocket *)sock didConnectToHost :(NSString *)host port:(UINt16)port;

當socket連接正準備讀和寫的時候調(diào)用胜蛉,host屬性是一個IP地址挠进,而不是一個DNS 名稱

-(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long) tag;

當socket已完成所要求的數(shù)據(jù)讀入內(nèi)存時調(diào)用色乾,如果有錯誤則不調(diào)用

-(void)onSocket:(Asyncsocket *)sock didReadPartialDataOfLength:(NSUInteger)partiaLength tag:(long)tag;

當一個socket讀取數(shù)據(jù),但尚未完成讀操作的時候調(diào)用领突,如果使用 readToData: or readToLength: 方法 會發(fā)生,可以被用來更新進度條等東西

-(void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag;

當一個socket已完成請求數(shù)據(jù)的寫入時候調(diào)用

-(void)onSocket:(AsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag;

當一個socket寫入一些數(shù)據(jù)暖璧,但還沒有完成整個寫入時調(diào)用,它可以用來更新進度條等東西

-(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag elapsed:(NSTimeInterval)exapsed bytesDone:(NSUInteger)length

使用讀操作已超時但還沒完成時調(diào)用君旦,此方法允許隨意延遲超時澎办,如果返回一個正的時間間隔,讀取的超時將有一定量的擴展金砍,如果不實現(xiàn)這個方法局蚀,或會像往常一樣返回一個負的時間間隔,elapsed參數(shù)是? 原超時的總和恕稠,加上先前通過這種方法添加的任何補充琅绅, length參數(shù)是 讀操作到目前為止已讀取的字節(jié)數(shù), 注意谱俭,如果返回正數(shù)的話奉件,這個方法可能被一個單獨的讀取多次調(diào)用

-(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutWriteWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length;

如果一個寫操作已達到其超時但還沒完成時調(diào)用宵蛀,同上

-(void)onSocketDidSecure:(AsyncSocket *)sock;

在socket成功完成ssl/tls協(xié)商時調(diào)用昆著,此方法除非你使用提供startTLS方法時候才調(diào)用,

如果ssl/tls是無效的證書术陶,socket將會立即關(guān)閉凑懂,onSocket:willDisconnectWithError:代理方法竟會與特定的ssl錯誤代碼一起調(diào)用

-(BOOL)canSafelySetDelegate

用來查看在改變它之前,是否帶有與當前的委托有懸而未決的業(yè)務(wù)(讀/寫)梧宫。當然接谨,應(yīng)在安全連接或接受委托之前改變委托

一旦接收或連接方法之一被調(diào)用,AsyncSocket實例會被鎖定塘匣,其他接收/連接方法在沒有先斷開socket不會被調(diào)用

如果嘗試失敗或超時脓豪,這些方法要么返回NO 要么調(diào)用 onSocket:willDisconnectWithError: 或 onSockedDidDisconnect

當傳入的連接被接受,AsyncSocket調(diào)用多個委托方法忌卤。這些方法按照時間順序排列:

1.onSocket:didAcceptNewSocket:

2.onSocket:wantsRunLoopForNewSocket:

3. onSocketWillConnect:

你的服務(wù)器的代碼將需要保留公認的socket(如果要接受它)扫夜,最好的地方是要做到這一點可能在onSocket:didAcceptNewSocket:方法

在讀和寫流已經(jīng)為新接受的socket設(shè)置,onSocket:didConnectToHost:port 方法將在適當?shù)倪\行循環(huán)調(diào)用

多線程注意驰徊,如果要想通過實施onSocket:wantsRunLoopForNewSocket:笤闯,移動另一個新接受的socket去到另一個循環(huán)的socket。然后棍厂,應(yīng)該在調(diào)用讀和寫或者startTLS方法前颗味,等待直到onSocket:didConnectToHost:port:方法。否則讀和寫時間原定于不正確的runloop牺弹,混亂可能會隨之而來

-(BOOL)acceptOnPort:(UInit16)port error:(NSError **)errPtr;

告訴socket開始聽取和接受制定端口上的連接浦马,當一個連接到來的時候时呀,AsyncSocket實例將調(diào)用各種委托方法,socket將聽取所有可用的接口(wifi,以太網(wǎng)等)

-(BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error :(NSError **)errPtr;

連接給定的主機和端口晶默,主機hostname可以是域名或者是Ip地址

-(BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError *)errPtr;

連接到一個給定的地址退唠,制定一個sockaddr結(jié)構(gòu)包裹住一個NSData對象,例如,NSData對象從NSNetService的地址方法返回,如果有一個現(xiàn)有的sockaddr結(jié)構(gòu)荤胁,可以將它轉(zhuǎn)換到一個NSData對象瞧预,像這樣:

struct sockaddr sa? -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len];

struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len];

-(void)disconnect;

立即斷開,任何未處理的讀或?qū)懚紝⒈粊G棄

如果socket還沒有斷開仅政,在這個方法返回之前垢油,onSocketDidDisconnect 委托方法將會被立即調(diào)用

注意推薦釋放AsyncSocket實例的方式:

[asyncSocket setDelegate:nil];

[asyncSocket disconnect];

[asyncSocket release];

-(void)disconnectAfterReading;

在已經(jīng)完成了所有懸而未決的讀取時 斷開,在調(diào)用之后,讀取和寫入方法將無用,socket將斷開 即使仍有待寫入

- (NSString *)connectedHost;

- (UInt16)connectedPort;

- (NSString *)localHost;

- (UInt16)localPort;

返回本地和遠程主機和端口給連接的socket圆丹,如果沒有連接會返回nil或0,主機將會是一個IP地址

-(NSData *)connectedAddress

-(NSData *)localAddresss

返回本地和遠程的地址給連接的socket滩愁,指定一個socketaddr結(jié)構(gòu)包裹在一個NSData對象

readData和writeData方法不會是block(它們是異步的)

當讀完成 onSocket:didReadData:withTag: 委托方法時調(diào)用

當寫完成 onSocket:didWriteDataWithTag: 委托方法時調(diào)用

可以選擇任何讀/寫操作的超時設(shè)置(為了不超時,使用負時間間隔辫封。)

如果讀/寫操作超時硝枉,相應(yīng)的 onSocket:shouldTimeout...委托方法被調(diào)用去選擇性地允許我們?nèi)パ娱L超時

超時后,onSocket:willDisconnectWithError: 方法被調(diào)用,緊接著是 onSocketDidDisconnect

tag是為了方便倦微,可以使用它作為數(shù)組的索引妻味、步數(shù)、state id 欣福、指針等

-(void)readDataWithTimeout:(NSTimeInterval)tiemout tag:(long)tag;

讀取socket上第一次成為可用的字節(jié),如果timeout值是負數(shù)的责球,讀操作將不使用timeout

- (void)readDataWithTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInterger)offset tag:(long)tag;

讀取socket上第一次成為可用的字節(jié)

字節(jié)將被追加到給定的字節(jié)緩沖區(qū),從給定的偏移量開始

如果需要拓劝,給定的緩沖區(qū)大小將會自動增加

如果timeout值是負數(shù)的雏逾,讀操作將不使用timeout

如果緩沖區(qū)為空,socket會為我們創(chuàng)建一個緩沖區(qū)

如果bufferOffset是大于給定的緩沖區(qū)的長度郑临,該方法將無用栖博,委托將不會被調(diào)用

如果你傳遞一個緩沖區(qū),當AsyncSocket在使用它的時候你不能以任何方式改變它

完成之后厢洞,onSocket:didReadData:withTag 返回的數(shù)據(jù)將是一個給定的緩沖區(qū)的子集

也就是說仇让,它將會被引用到被追加的給定的緩沖區(qū)的字節(jié)

-(void)readDataToLength:(NSUInterger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag;

讀取給定的字節(jié)數(shù),如果length為0犀变,方法將無用妹孙,委托將不會被調(diào)用

-(void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)tiemout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;

讀取給定的字節(jié)數(shù),在給定的偏移開始,字節(jié)將被追加到給定的字節(jié)緩沖區(qū)

-(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;

讀取字節(jié)直到(包括)傳入的作為分隔的"data"參數(shù)

如果傳遞0或者0長度的數(shù)據(jù)获枝,"data"參數(shù)蠢正,該方法將無用,委托將不會被調(diào)用

從socket讀取一行省店,使用"data"參數(shù)作為行的分隔符 (如HTTP的CRLF)

注意嚣崭,此方法不是字符集笨触,因此,如果一個分隔符出現(xiàn)雹舀,它自然可以作為進行編碼的一部分芦劣,讀取將提前結(jié)束

-(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;

讀取字節(jié)直到(包括)傳入的作為分隔的“data”參數(shù),在給定的偏移量開始说榆,字節(jié)將被追加到給定的字節(jié)緩沖區(qū)虚吟。

從socket讀取一行,使用"data"參數(shù)作為行的分隔符(如HTTP的CRLF)

-(void)writeData:(NSData *)data withTimeout:(NSTimeInterval) timeout tag:(long)tag;

將data寫入socket签财,當完成的時候委托被調(diào)用

- (float)progressOfReadReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;

- (float)progressOfWriteReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;

返回當前讀或?qū)懙倪M度串慰,從0.0 到 1.0 或者 如果沒有讀/寫的時候返回Nan(使用isNan來檢查)

tag、done唱蒸、total如果不為空的話邦鲫,它們將會被填補

- (void)startTLS:(NSDictionary *)tlsSettings;

確保使用ssl/tls連接

這方法可被隨時調(diào)用,tls握手將會發(fā)生在所有懸而未決的讀/寫完成之后神汹。這緊跟著一個發(fā)送依賴 StartTLS消息的協(xié)議選項庆捺,在排隊升級到TLS的同一時間,而不必等待寫入完成屁魏。在這個方法被調(diào)用后,任何讀寫計劃 將會發(fā)生在安全鏈接

對于可能的keys和TLS設(shè)置的值是有據(jù)可查的

一些可能的keys是:

* - kCFStreamSSLLevel

* - kCFStreamSSLAllowsExpiredCertificates

* - kCFStreamSSLAllowsExpiredRoots

* - kCFStreamSSLAllowsAnyRoot

* - kCFStreamSSLValidatesCertificateChain

* - kCFStreamSSLPeerName

* - kCFStreamSSLCertificates

* - kCFStreamSSLIsServer

如果你傳遞空或者空字典滔以,將使用默認的字典

默認設(shè)置將檢查以確保由簽署可信的第三方證書機構(gòu)和沒有過期的遠程連接的證書

然而榨崩,它不會驗證證書上的名字鹅很,除非你給它一個名字,通過kCFStreamSSLPeerName鍵去驗證

這對安全的影響是重要的理解

想象一下你正試圖創(chuàng)建一個到MySecureServer.com的安全連接,但因為一個被攻擊的DNS服務(wù)器披诗,所以你的socket被定向到MaliciousServer.com

如果你只是使用默認設(shè)置,MaliciousServer.com 有一個有效的證書

默認設(shè)置將無法監(jiān)測到任何問題立磁,因為證書是有效的

在這個特殊的情況下呈队,要妥善保護你的連接,應(yīng)設(shè)置kCFStreamSSLPeerName性質(zhì)為MySecureServer.com.

如果事前你不知道對等的名字的遠程主機(例如唱歧,你不確認它是domain.com" or "www.domain.com")宪摧,那么你可以使用默認設(shè)置來驗證證書,然后在獲得驗證的發(fā)行后使用X509Certificate類來驗證,X509Certificate類的CocoaAsyncSocket開源項目的一部分

-(void)enablePrebuffering

對于處理readDataToData請求颅崩,數(shù)據(jù)是必須從socket以小增量的方式讀取出來的

性能通過允許AsyncSocket去一次性讀大塊的數(shù)據(jù)和存儲任何一個小的內(nèi)部緩沖區(qū)溢出的東西來大大提高

這被稱為預(yù)緩沖几于,就好像一些數(shù)據(jù)在你要求它之前就可能被讀取出來

如果你經(jīng)常使用readDataToData,使用預(yù)緩沖會有更好的性能沿后,尤其是在iphone上

默認的預(yù)緩沖狀態(tài)是由DEFAULT_PREBUFFERING 定義控制的沿彭,強烈建議設(shè)置其為yes

這方法存在一些預(yù)緩沖需要一些不可預(yù)見的原因被默認禁用的情況,這時尖滚,這種方法存在允許當就緒時喉刘,可輕松啟用預(yù)緩沖

-(BOOL)moveToRunLoop:(NSRunLoop *)runLoop;

當你創(chuàng)建一個AsyncSocket瞧柔,它被添加到當前線程runloop

對于手動創(chuàng)建的socket,在線程上你打算使用它睦裳,它是最容易簡單的創(chuàng)建的線程上的socket

當一個新的socket被接受造锅,委托方法 onSocket:wantsRunLoopForNewSocket 會被調(diào)用 允許你在一個單獨的線程上放置socket,這個工作最好結(jié)合在同一個線程池設(shè)計

如果廉邑,但是哥蔚,在一個單獨的線程上,在之后的時間蛛蒙,你需要移動一個socket肺素,這個方法可以用來完成任務(wù)

此方法必須從 當前運行的 線程/runloop 的socket 調(diào)用

注意:此方法調(diào)用后,所有進一步的方法應(yīng)該從給定的runloop上調(diào)用這個對象

此外宇驾,所有委托調(diào)用將會發(fā)送到給定的runloop

- (BOOL)setRunLoopModes:(NSArray *)runLoopModes;

- (BOOL)addRunLoopMode:(NSString *)runLoopMode;

- (BOOL)removeRunLoopMode:(NSString *)runLoopMode;

允許你配置 socket 使用的 運行循環(huán)模式

運行循環(huán)模式設(shè)置默認是NSRunLoopCommonModes

如果你想你的socket 在其他模式下繼續(xù)操作倍靡,你可能需要添加模式 NSModalPanelRunLoopMode 或者 NSEventTrackingRunLoopMode ,或者你可能只想使用 NSRunLoopCommonModes

可接受的socket將自動 繼承相同的運行循環(huán)模式就像偵聽socket

注意:NSRunLoopCommonModes 定義在10.5,對于之前的版本可使用 kCFRunLoopCommonModes

-(NSArray *)runLoopModes

返回當前正在運行的循環(huán)模式的AsyncSocket實例课舍, run loop modes的默認設(shè)置是NSDefaultRunLoopMode

-(NSData *)unreadData;

一個錯誤的事件塌西,在 onSocket:willDisconnectWithError: 將會被調(diào)用 去讀取留在socket上的任何數(shù)據(jù)

+ (NSData *)CRLFData;?? // 0x0D0A

各方法的解析

-(void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err;

發(fā)生錯誤,socket關(guān)閉筝尾,可以在call-back過程調(diào)用"unreadData"去取得socket的最后的數(shù)據(jù)字節(jié)捡需,當連接的時候,該委托方法在??? onSocket:didAcceptNewSocket: 或者 onSocket:didConnectToHost: 之前調(diào)用

-(void)onSocketDidDisconnect:(ASyncSocket *)sock;

當socket由于或沒有錯誤而斷開連接筹淫,如果你想要在斷開連接后release socket站辉,在此方法工作,而在onSocket:willDisconnectWithError 釋放則不安全

-(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket;

當產(chǎn)生一個socket去處理連接時調(diào)用损姜,此方法會返回 線程上的run-loop 的新的socket和其應(yīng)處理的委托饰剥,如果省略,則使用[NSRunLoop cunrrentRunLoop]

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

-(void)onSocket:(AsyncSocket *)sock didConnectToHost :(NSString *)host port:(UINt16)port;

當socket連接正準備讀和寫的時候調(diào)用摧阅,host屬性是一個IP地址汰蓉,而不是一個DNS 名稱

-(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long) tag;

當socket已完成所要求的數(shù)據(jù)讀入內(nèi)存時調(diào)用,如果有錯誤則不調(diào)用

-(void)onSocket:(Asyncsocket *)sock didReadPartialDataOfLength:(NSUInteger)partiaLength tag:(long)tag;

當一個socket讀取數(shù)據(jù)棒卷,但尚未完成讀操作的時候調(diào)用顾孽,如果使用 readToData: or readToLength: 方法 會發(fā)生,可以被用來更新進度條等東西

-(void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag;

當一個socket已完成請求數(shù)據(jù)的寫入時候調(diào)用

-(void)onSocket:(AsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag;

當一個socket寫入一些數(shù)據(jù),但還沒有完成整個寫入時調(diào)用比规,它可以用來更新進度條等東西

-(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag elapsed:(NSTimeInterval)exapsed bytesDone:(NSUInteger)length

使用讀操作已超時但還沒完成時調(diào)用若厚,此方法允許隨意延遲超時,如果返回一個正的時間間隔蜒什,讀取的超時將有一定量的擴展,如果不實現(xiàn)這個方法,或會像往常一樣返回一個負的時間間隔乞封,elapsed參數(shù)是? 原超時的總和做裙,加上先前通過這種方法添加的任何補充, length參數(shù)是 讀操作到目前為止已讀取的字節(jié)數(shù)肃晚, 注意锚贱,如果返回正數(shù)的話,這個方法可能被一個單獨的讀取多次調(diào)用

-(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutWriteWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length;

如果一個寫操作已達到其超時但還沒完成時調(diào)用关串,同上

-(void)onSocketDidSecure:(AsyncSocket *)sock;

在socket成功完成ssl/tls協(xié)商時調(diào)用拧廊,此方法除非你使用提供startTLS方法時候才調(diào)用,

如果ssl/tls是無效的證書晋修,socket將會立即關(guān)閉吧碾,onSocket:willDisconnectWithError:代理方法竟會與特定的ssl錯誤代碼一起調(diào)用

-(BOOL)canSafelySetDelegate

用來查看在改變它之前,是否帶有與當前的委托有懸而未決的業(yè)務(wù)(讀/寫)墓卦。當然倦春,應(yīng)在安全連接或接受委托之前改變委托

一旦接收或連接方法之一被調(diào)用,AsyncSocket實例會被鎖定落剪,其他接收/連接方法在沒有先斷開socket不會被調(diào)用

如果嘗試失敗或超時睁本,這些方法要么返回NO 要么調(diào)用 onSocket:willDisconnectWithError: 或 onSockedDidDisconnect

當傳入的連接被接受,AsyncSocket調(diào)用多個委托方法忠怖。這些方法按照時間順序排列:

1.onSocket:didAcceptNewSocket:

2.onSocket:wantsRunLoopForNewSocket:

3. onSocketWillConnect:

你的服務(wù)器的代碼將需要保留公認的socket(如果要接受它)呢堰,最好的地方是要做到這一點可能在onSocket:didAcceptNewSocket:方法

在讀和寫流已經(jīng)為新接受的socket設(shè)置,onSocket:didConnectToHost:port 方法將在適當?shù)倪\行循環(huán)調(diào)用

多線程注意凡泣,如果要想通過實施onSocket:wantsRunLoopForNewSocket:枉疼,移動另一個新接受的socket去到另一個循環(huán)的socket。然后鞋拟,應(yīng)該在調(diào)用讀和寫或者startTLS方法前骂维,等待直到onSocket:didConnectToHost:port:方法。否則讀和寫時間原定于不正確的runloop严卖,混亂可能會隨之而來

-(BOOL)acceptOnPort:(UInit16)port error:(NSError **)errPtr;

告訴socket開始聽取和接受制定端口上的連接席舍,當一個連接到來的時候,AsyncSocket實例將調(diào)用各種委托方法哮笆,socket將聽取所有可用的接口(wifi,以太網(wǎng)等)

-(BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error :(NSError **)errPtr;

連接給定的主機和端口,主機hostname可以是域名或者是Ip地址

-(BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError *)errPtr;

連接到一個給定的地址汰扭,制定一個sockaddr結(jié)構(gòu)包裹住一個NSData對象,例如稠肘,NSData對象從NSNetService的地址方法返回,如果有一個現(xiàn)有的sockaddr結(jié)構(gòu),可以將它轉(zhuǎn)換到一個NSData對象萝毛,像這樣:

struct sockaddr sa? -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len];

struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len];

-(void)disconnect;

立即斷開项阴,任何未處理的讀或?qū)懚紝⒈粊G棄

如果socket還沒有斷開,在這個方法返回之前,onSocketDidDisconnect 委托方法將會被立即調(diào)用

注意推薦釋放AsyncSocket實例的方式:

[asyncSocket setDelegate:nil];

[asyncSocket disconnect];

[asyncSocket release];

-(void)disconnectAfterReading;

在已經(jīng)完成了所有懸而未決的讀取時 斷開,在調(diào)用之后环揽,讀取和寫入方法將無用,socket將斷開 即使仍有待寫入

- (NSString *)connectedHost;

- (UInt16)connectedPort;

- (NSString *)localHost;

- (UInt16)localPort;

返回本地和遠程主機和端口給連接的socket略荡,如果沒有連接會返回nil或0,主機將會是一個IP地址

-(NSData *)connectedAddress

-(NSData *)localAddresss

返回本地和遠程的地址給連接的socket,指定一個socketaddr結(jié)構(gòu)包裹在一個NSData對象

readData和writeData方法不會是block(它們是異步的)

當讀完成 onSocket:didReadData:withTag: 委托方法時調(diào)用

當寫完成 onSocket:didWriteDataWithTag: 委托方法時調(diào)用

可以選擇任何讀/寫操作的超時設(shè)置(為了不超時歉胶,使用負時間間隔汛兜。)

如果讀/寫操作超時,相應(yīng)的 onSocket:shouldTimeout...委托方法被調(diào)用去選擇性地允許我們?nèi)パ娱L超時

超時后通今,onSocket:willDisconnectWithError: 方法被調(diào)用,緊接著是 onSocketDidDisconnect

tag是為了方便粥谬,可以使用它作為數(shù)組的索引、步數(shù)辫塌、state id 臼氨、指針等

-(void)readDataWithTimeout:(NSTimeInterval)tiemout tag:(long)tag;

讀取socket上第一次成為可用的字節(jié),如果timeout值是負數(shù)的,讀操作將不使用timeout

- (void)readDataWithTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInterger)offset tag:(long)tag;

讀取socket上第一次成為可用的字節(jié)

字節(jié)將被追加到給定的字節(jié)緩沖區(qū)储矩,從給定的偏移量開始

如果需要椰苟,給定的緩沖區(qū)大小將會自動增加

如果timeout值是負數(shù)的抑月,讀操作將不使用timeout

如果緩沖區(qū)為空谦絮,socket會為我們創(chuàng)建一個緩沖區(qū)

如果bufferOffset是大于給定的緩沖區(qū)的長度层皱,該方法將無用叫胖,委托將不會被調(diào)用

如果你傳遞一個緩沖區(qū)瓮增,當AsyncSocket在使用它的時候你不能以任何方式改變它

完成之后,onSocket:didReadData:withTag 返回的數(shù)據(jù)將是一個給定的緩沖區(qū)的子集

也就是說砸捏,它將會被引用到被追加的給定的緩沖區(qū)的字節(jié)

-(void)readDataToLength:(NSUInterger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag;

讀取給定的字節(jié)數(shù)梆暖,如果length為0轰驳,方法將無用滑废,委托將不會被調(diào)用

-(void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)tiemout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;

讀取給定的字節(jié)數(shù),在給定的偏移開始蠕趁,字節(jié)將被追加到給定的字節(jié)緩沖區(qū)

-(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;

讀取字節(jié)直到(包括)傳入的作為分隔的"data"參數(shù)

如果傳遞0或者0長度的數(shù)據(jù),"data"參數(shù)腊状,該方法將無用,委托將不會被調(diào)用

從socket讀取一行映屋,使用"data"參數(shù)作為行的分隔符 (如HTTP的CRLF)

注意棚点,此方法不是字符集,因此贬循,如果一個分隔符出現(xiàn)甘有,它自然可以作為進行編碼的一部分,讀取將提前結(jié)束

-(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;

讀取字節(jié)直到(包括)傳入的作為分隔的“data”參數(shù)滤愕,在給定的偏移量開始间影,字節(jié)將被追加到給定的字節(jié)緩沖區(qū)。

從socket讀取一行付燥,使用"data"參數(shù)作為行的分隔符(如HTTP的CRLF)

-(void)writeData:(NSData *)data withTimeout:(NSTimeInterval) timeout tag:(long)tag;

將data寫入socket,當完成的時候委托被調(diào)用

- (float)progressOfReadReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;

- (float)progressOfWriteReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;

返回當前讀或?qū)懙倪M度勋颖,從0.0 到 1.0 或者 如果沒有讀/寫的時候返回Nan(使用isNan來檢查)

tag、done茄厘、total如果不為空的話,它們將會被填補

- (void)startTLS:(NSDictionary *)tlsSettings;

確保使用ssl/tls連接

這方法可被隨時調(diào)用,tls握手將會發(fā)生在所有懸而未決的讀/寫完成之后葛假。這緊跟著一個發(fā)送依賴 StartTLS消息的協(xié)議選項,在排隊升級到TLS的同一時間带斑,而不必等待寫入完成妈候。在這個方法被調(diào)用后,任何讀寫計劃 將會發(fā)生在安全鏈接

對于可能的keys和TLS設(shè)置的值是有據(jù)可查的

一些可能的keys是:

* - kCFStreamSSLLevel

* - kCFStreamSSLAllowsExpiredCertificates

* - kCFStreamSSLAllowsExpiredRoots

* - kCFStreamSSLAllowsAnyRoot

* - kCFStreamSSLValidatesCertificateChain

* - kCFStreamSSLPeerName

* - kCFStreamSSLCertificates

* - kCFStreamSSLIsServer

如果你傳遞空或者空字典,將使用默認的字典

默認設(shè)置將檢查以確保由簽署可信的第三方證書機構(gòu)和沒有過期的遠程連接的證書

然而幔虏,它不會驗證證書上的名字,除非你給它一個名字主胧,通過kCFStreamSSLPeerName鍵去驗證

這對安全的影響是重要的理解

想象一下你正試圖創(chuàng)建一個到MySecureServer.com的安全連接,但因為一個被攻擊的DNS服務(wù)器夷都,所以你的socket被定向到MaliciousServer.com

如果你只是使用默認設(shè)置蛤虐,MaliciousServer.com 有一個有效的證書

默認設(shè)置將無法監(jiān)測到任何問題,因為證書是有效的

在這個特殊的情況下执泰,要妥善保護你的連接铺坞,應(yīng)設(shè)置kCFStreamSSLPeerName性質(zhì)為MySecureServer.com.

如果事前你不知道對等的名字的遠程主機(例如,你不確認它是domain.com" or "www.domain.com")擒滑,那么你可以使用默認設(shè)置來驗證證書,然后在獲得驗證的發(fā)行后使用X509Certificate類來驗證,X509Certificate類的CocoaAsyncSocket開源項目的一部分

-(void)enablePrebuffering

對于處理readDataToData請求钝诚,數(shù)據(jù)是必須從socket以小增量的方式讀取出來的

性能通過允許AsyncSocket去一次性讀大塊的數(shù)據(jù)和存儲任何一個小的內(nèi)部緩沖區(qū)溢出的東西來大大提高

這被稱為預(yù)緩沖潘拱,就好像一些數(shù)據(jù)在你要求它之前就可能被讀取出來

如果你經(jīng)常使用readDataToData,使用預(yù)緩沖會有更好的性能禽最,尤其是在iphone上

默認的預(yù)緩沖狀態(tài)是由DEFAULT_PREBUFFERING 定義控制的,強烈建議設(shè)置其為yes

這方法存在一些預(yù)緩沖需要一些不可預(yù)見的原因被默認禁用的情況,這時仅叫,這種方法存在允許當就緒時,可輕松啟用預(yù)緩沖

-(BOOL)moveToRunLoop:(NSRunLoop *)runLoop;

當你創(chuàng)建一個AsyncSocket遂跟,它被添加到當前線程runloop

對于手動創(chuàng)建的socket,在線程上你打算使用它哄尔,它是最容易簡單的創(chuàng)建的線程上的socket

當一個新的socket被接受,委托方法 onSocket:wantsRunLoopForNewSocket 會被調(diào)用 允許你在一個單獨的線程上放置socket,這個工作最好結(jié)合在同一個線程池設(shè)計

如果窄锅,但是追驴,在一個單獨的線程上,在之后的時間丙曙,你需要移動一個socket,這個方法可以用來完成任務(wù)

此方法必須從 當前運行的 線程/runloop 的socket 調(diào)用

注意:此方法調(diào)用后薄霜,所有進一步的方法應(yīng)該從給定的runloop上調(diào)用這個對象

此外否副,所有委托調(diào)用將會發(fā)送到給定的runloop

- (BOOL)setRunLoopModes:(NSArray *)runLoopModes;

- (BOOL)addRunLoopMode:(NSString *)runLoopMode;

- (BOOL)removeRunLoopMode:(NSString *)runLoopMode;

允許你配置 socket 使用的 運行循環(huán)模式

運行循環(huán)模式設(shè)置默認是NSRunLoopCommonModes

如果你想你的socket 在其他模式下繼續(xù)操作,你可能需要添加模式 NSModalPanelRunLoopMode 或者 NSEventTrackingRunLoopMode ,或者你可能只想使用 NSRunLoopCommonModes

可接受的socket將自動 繼承相同的運行循環(huán)模式就像偵聽socket

注意:NSRunLoopCommonModes 定義在10.5,對于之前的版本可使用 kCFRunLoopCommonModes

-(NSArray *)runLoopModes

返回當前正在運行的循環(huán)模式的AsyncSocket實例另患, run loop modes的默認設(shè)置是NSDefaultRunLoopMode

-(NSData *)unreadData;

一個錯誤的事件,在 onSocket:willDisconnectWithError: 將會被調(diào)用 去讀取留在socket上的任何數(shù)據(jù)

+ (NSData *)CRLFData;?? // 0x0D0A

各方法的解析

-(void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err;

發(fā)生錯誤,socket關(guān)閉纤泵,可以在call-back過程調(diào)用"unreadData"去取得socket的最后的數(shù)據(jù)字節(jié)诲锹,當連接的時候,該委托方法在??? onSocket:didAcceptNewSocket: 或者 onSocket:didConnectToHost: 之前調(diào)用

-(void)onSocketDidDisconnect:(ASyncSocket *)sock;

當socket由于或沒有錯誤而斷開連接,如果你想要在斷開連接后release socket桥爽,在此方法工作,而在onSocket:willDisconnectWithError 釋放則不安全

-(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket;

當產(chǎn)生一個socket去處理連接時調(diào)用,此方法會返回 線程上的run-loop 的新的socket和其應(yīng)處理的委托缕碎,如果省略,則使用[NSRunLoop cunrrentRunLoop]

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

-(void)onSocket:(AsyncSocket *)sock didConnectToHost :(NSString *)host port:(UINt16)port;

當socket連接正準備讀和寫的時候調(diào)用,host屬性是一個IP地址熏迹,而不是一個DNS 名稱

-(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long) tag;

當socket已完成所要求的數(shù)據(jù)讀入內(nèi)存時調(diào)用,如果有錯誤則不調(diào)用

-(void)onSocket:(Asyncsocket *)sock didReadPartialDataOfLength:(NSUInteger)partiaLength tag:(long)tag;

當一個socket讀取數(shù)據(jù),但尚未完成讀操作的時候調(diào)用,如果使用 readToData: or readToLength: 方法 會發(fā)生,可以被用來更新進度條等東西

-(void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag;

當一個socket已完成請求數(shù)據(jù)的寫入時候調(diào)用

-(void)onSocket:(AsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag;

當一個socket寫入一些數(shù)據(jù)寇仓,但還沒有完成整個寫入時調(diào)用俭嘁,它可以用來更新進度條等東西

-(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag elapsed:(NSTimeInterval)exapsed bytesDone:(NSUInteger)length

使用讀操作已超時但還沒完成時調(diào)用罢猪,此方法允許隨意延遲超時粘捎,如果返回一個正的時間間隔,讀取的超時將有一定量的擴展,如果不實現(xiàn)這個方法,或會像往常一樣返回一個負的時間間隔狱掂,elapsed參數(shù)是? 原超時的總和,加上先前通過這種方法添加的任何補充, length參數(shù)是 讀操作到目前為止已讀取的字節(jié)數(shù)兆沙, 注意,如果返回正數(shù)的話曲楚,這個方法可能被一個單獨的讀取多次調(diào)用

-(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutWriteWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length;

如果一個寫操作已達到其超時但還沒完成時調(diào)用,同上

-(void)onSocketDidSecure:(AsyncSocket *)sock;

在socket成功完成ssl/tls協(xié)商時調(diào)用,此方法除非你使用提供startTLS方法時候才調(diào)用,

如果ssl/tls是無效的證書惋耙,socket將會立即關(guān)閉婿屹,onSocket:willDisconnectWithError:代理方法竟會與特定的ssl錯誤代碼一起調(diào)用

-(BOOL)canSafelySetDelegate

用來查看在改變它之前届腐,是否帶有與當前的委托有懸而未決的業(yè)務(wù)(讀/寫)。當然,應(yīng)在安全連接或接受委托之前改變委托

一旦接收或連接方法之一被調(diào)用助赞,AsyncSocket實例會被鎖定魁兼,其他接收/連接方法在沒有先斷開socket不會被調(diào)用

如果嘗試失敗或超時盖呼,這些方法要么返回NO 要么調(diào)用 onSocket:willDisconnectWithError: 或 onSockedDidDisconnect

當傳入的連接被接受约炎,AsyncSocket調(diào)用多個委托方法憾朴。這些方法按照時間順序排列:

1.onSocket:didAcceptNewSocket:

2.onSocket:wantsRunLoopForNewSocket:

3. onSocketWillConnect:

你的服務(wù)器的代碼將需要保留公認的socket(如果要接受它)砾省,最好的地方是要做到這一點可能在onSocket:didAcceptNewSocket:方法

在讀和寫流已經(jīng)為新接受的socket設(shè)置轩性,onSocket:didConnectToHost:port 方法將在適當?shù)倪\行循環(huán)調(diào)用

多線程注意,如果要想通過實施onSocket:wantsRunLoopForNewSocket:绅作,移動另一個新接受的socket去到另一個循環(huán)的socket个少。然后岂贩,應(yīng)該在調(diào)用讀和寫或者startTLS方法前茫经,等待直到onSocket:didConnectToHost:port:方法。否則讀和寫時間原定于不正確的runloop,混亂可能會隨之而來

-(BOOL)acceptOnPort:(UInit16)port error:(NSError **)errPtr;

告訴socket開始聽取和接受制定端口上的連接卸伞,當一個連接到來的時候抹镊,AsyncSocket實例將調(diào)用各種委托方法荤傲,socket將聽取所有可用的接口(wifi,以太網(wǎng)等)

-(BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error :(NSError **)errPtr;

連接給定的主機和端口垮耳,主機hostname可以是域名或者是Ip地址

-(BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError *)errPtr;

連接到一個給定的地址,制定一個sockaddr結(jié)構(gòu)包裹住一個NSData對象,例如遂黍,NSData對象從NSNetService的地址方法返回,如果有一個現(xiàn)有的sockaddr結(jié)構(gòu)终佛,可以將它轉(zhuǎn)換到一個NSData對象,像這樣:

struct sockaddr sa? -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len];

struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len];

-(void)disconnect;

立即斷開雾家,任何未處理的讀或?qū)懚紝⒈粊G棄

如果socket還沒有斷開铃彰,在這個方法返回之前,onSocketDidDisconnect 委托方法將會被立即調(diào)用

注意推薦釋放AsyncSocket實例的方式:

[asyncSocket setDelegate:nil];

[asyncSocket disconnect];

[asyncSocket release];

-(void)disconnectAfterReading;

在已經(jīng)完成了所有懸而未決的讀取時 斷開,在調(diào)用之后榜贴,讀取和寫入方法將無用,socket將斷開 即使仍有待寫入

- (NSString *)connectedHost;

- (UInt16)connectedPort;

- (NSString *)localHost;

- (UInt16)localPort;

返回本地和遠程主機和端口給連接的socket豌研,如果沒有連接會返回nil或0,主機將會是一個IP地址

-(NSData *)connectedAddress

-(NSData *)localAddresss

返回本地和遠程的地址給連接的socket,指定一個socketaddr結(jié)構(gòu)包裹在一個NSData對象

readData和writeData方法不會是block(它們是異步的)

當讀完成 onSocket:didReadData:withTag: 委托方法時調(diào)用

當寫完成 onSocket:didWriteDataWithTag: 委托方法時調(diào)用

可以選擇任何讀/寫操作的超時設(shè)置(為了不超時唬党,使用負時間間隔鹃共。)

如果讀/寫操作超時,相應(yīng)的 onSocket:shouldTimeout...委托方法被調(diào)用去選擇性地允許我們?nèi)パ娱L超時

超時后驶拱,onSocket:willDisconnectWithError: 方法被調(diào)用,緊接著是 onSocketDidDisconnect

tag是為了方便霜浴,可以使用它作為數(shù)組的索引、步數(shù)蓝纲、state id 阴孟、指針等

-(void)readDataWithTimeout:(NSTimeInterval)tiemout tag:(long)tag;

讀取socket上第一次成為可用的字節(jié),如果timeout值是負數(shù)的,讀操作將不使用timeout

- (void)readDataWithTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInterger)offset tag:(long)tag;

讀取socket上第一次成為可用的字節(jié)

字節(jié)將被追加到給定的字節(jié)緩沖區(qū)税迷,從給定的偏移量開始

如果需要永丝,給定的緩沖區(qū)大小將會自動增加

如果timeout值是負數(shù)的,讀操作將不使用timeout

如果緩沖區(qū)為空箭养,socket會為我們創(chuàng)建一個緩沖區(qū)

如果bufferOffset是大于給定的緩沖區(qū)的長度慕嚷,該方法將無用,委托將不會被調(diào)用

如果你傳遞一個緩沖區(qū)毕泌,當AsyncSocket在使用它的時候你不能以任何方式改變它

完成之后喝检,onSocket:didReadData:withTag 返回的數(shù)據(jù)將是一個給定的緩沖區(qū)的子集

也就是說,它將會被引用到被追加的給定的緩沖區(qū)的字節(jié)

-(void)readDataToLength:(NSUInterger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag;

讀取給定的字節(jié)數(shù)撼泛,如果length為0挠说,方法將無用,委托將不會被調(diào)用

-(void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)tiemout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;

讀取給定的字節(jié)數(shù),在給定的偏移開始愿题,字節(jié)將被追加到給定的字節(jié)緩沖區(qū)

-(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;

讀取字節(jié)直到(包括)傳入的作為分隔的"data"參數(shù)

如果傳遞0或者0長度的數(shù)據(jù)损俭,"data"參數(shù)蛙奖,該方法將無用,委托將不會被調(diào)用

從socket讀取一行撩炊,使用"data"參數(shù)作為行的分隔符 (如HTTP的CRLF)

注意外永,此方法不是字符集,因此拧咳,如果一個分隔符出現(xiàn)伯顶,它自然可以作為進行編碼的一部分,讀取將提前結(jié)束

-(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;

讀取字節(jié)直到(包括)傳入的作為分隔的“data”參數(shù)骆膝,在給定的偏移量開始祭衩,字節(jié)將被追加到給定的字節(jié)緩沖區(qū)。

從socket讀取一行阅签,使用"data"參數(shù)作為行的分隔符(如HTTP的CRLF)

-(void)writeData:(NSData *)data withTimeout:(NSTimeInterval) timeout tag:(long)tag;

將data寫入socket掐暮,當完成的時候委托被調(diào)用

- (float)progressOfReadReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;

- (float)progressOfWriteReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;

返回當前讀或?qū)懙倪M度,從0.0 到 1.0 或者 如果沒有讀/寫的時候返回Nan(使用isNan來檢查)

tag政钟、done路克、total如果不為空的話,它們將會被填補

- (void)startTLS:(NSDictionary *)tlsSettings;

確保使用ssl/tls連接

這方法可被隨時調(diào)用养交,tls握手將會發(fā)生在所有懸而未決的讀/寫完成之后精算。這緊跟著一個發(fā)送依賴 StartTLS消息的協(xié)議選項,在排隊升級到TLS的同一時間碎连,而不必等待寫入完成灰羽。在這個方法被調(diào)用后,任何讀寫計劃 將會發(fā)生在安全鏈接

對于可能的keys和TLS設(shè)置的值是有據(jù)可查的

一些可能的keys是:

* - kCFStreamSSLLevel

* - kCFStreamSSLAllowsExpiredCertificates

* - kCFStreamSSLAllowsExpiredRoots

* - kCFStreamSSLAllowsAnyRoot

* - kCFStreamSSLValidatesCertificateChain

* - kCFStreamSSLPeerName

* - kCFStreamSSLCertificates

* - kCFStreamSSLIsServer

如果你傳遞空或者空字典,將使用默認的字典

默認設(shè)置將檢查以確保由簽署可信的第三方證書機構(gòu)和沒有過期的遠程連接的證書

然而鱼辙,它不會驗證證書上的名字廉嚼,除非你給它一個名字,通過kCFStreamSSLPeerName鍵去驗證

這對安全的影響是重要的理解

想象一下你正試圖創(chuàng)建一個到MySecureServer.com的安全連接倒戏,但因為一個被攻擊的DNS服務(wù)器怠噪,所以你的socket被定向到MaliciousServer.com

如果你只是使用默認設(shè)置,MaliciousServer.com 有一個有效的證書

默認設(shè)置將無法監(jiān)測到任何問題杜跷,因為證書是有效的

在這個特殊的情況下舰绘,要妥善保護你的連接,應(yīng)設(shè)置kCFStreamSSLPeerName性質(zhì)為MySecureServer.com.

如果事前你不知道對等的名字的遠程主機(例如葱椭,你不確認它是domain.com" or "www.domain.com"),那么你可以使用默認設(shè)置來驗證證書口四,然后在獲得驗證的發(fā)行后使用X509Certificate類來驗證,X509Certificate類的CocoaAsyncSocket開源項目的一部分

-(void)enablePrebuffering

對于處理readDataToData請求孵运,數(shù)據(jù)是必須從socket以小增量的方式讀取出來的

性能通過允許AsyncSocket去一次性讀大塊的數(shù)據(jù)和存儲任何一個小的內(nèi)部緩沖區(qū)溢出的東西來大大提高

這被稱為預(yù)緩沖,就好像一些數(shù)據(jù)在你要求它之前就可能被讀取出來

如果你經(jīng)常使用readDataToData蔓彩,使用預(yù)緩沖會有更好的性能治笨,尤其是在iphone上

默認的預(yù)緩沖狀態(tài)是由DEFAULT_PREBUFFERING 定義控制的驳概,強烈建議設(shè)置其為yes

這方法存在一些預(yù)緩沖需要一些不可預(yù)見的原因被默認禁用的情況,這時旷赖,這種方法存在允許當就緒時顺又,可輕松啟用預(yù)緩沖

-(BOOL)moveToRunLoop:(NSRunLoop *)runLoop;

當你創(chuàng)建一個AsyncSocket,它被添加到當前線程runloop

對于手動創(chuàng)建的socket等孵,在線程上你打算使用它到千,它是最容易簡單的創(chuàng)建的線程上的socket

當一個新的socket被接受噩斟,委托方法 onSocket:wantsRunLoopForNewSocket 會被調(diào)用 允許你在一個單獨的線程上放置socket,這個工作最好結(jié)合在同一個線程池設(shè)計

如果,但是冗酿,在一個單獨的線程上,在之后的時間枕稀,你需要移動一個socket杀赢,這個方法可以用來完成任務(wù)

此方法必須從 當前運行的 線程/runloop 的socket 調(diào)用

注意:此方法調(diào)用后,所有進一步的方法應(yīng)該從給定的runloop上調(diào)用這個對象

此外棋恼,所有委托調(diào)用將會發(fā)送到給定的runloop

- (BOOL)setRunLoopModes:(NSArray *)runLoopModes;

- (BOOL)addRunLoopMode:(NSString *)runLoopMode;

- (BOOL)removeRunLoopMode:(NSString *)runLoopMode;

允許你配置 socket 使用的 運行循環(huán)模式

運行循環(huán)模式設(shè)置默認是NSRunLoopCommonModes

如果你想你的socket 在其他模式下繼續(xù)操作返弹,你可能需要添加模式 NSModalPanelRunLoopMode 或者 NSEventTrackingRunLoopMode ,或者你可能只想使用 NSRunLoopCommonModes

可接受的socket將自動 繼承相同的運行循環(huán)模式就像偵聽socket

注意:NSRunLoopCommonModes 定義在10.5,對于之前的版本可使用 kCFRunLoopCommonModes

-(NSArray *)runLoopModes

返回當前正在運行的循環(huán)模式的AsyncSocket實例爪飘, run loop modes的默認設(shè)置是NSDefaultRunLoopMode

-(NSData *)unreadData;

一個錯誤的事件义起,在 onSocket:willDisconnectWithError: 將會被調(diào)用 去讀取留在socket上的任何數(shù)據(jù)

+ (NSData *)CRLFData;?? // 0x0D0A

各方法的解析

-(void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err;

發(fā)生錯誤,socket關(guān)閉悦施,可以在call-back過程調(diào)用"unreadData"去取得socket的最后的數(shù)據(jù)字節(jié)并扇,當連接的時候,該委托方法在??? onSocket:didAcceptNewSocket: 或者 onSocket:didConnectToHost: 之前調(diào)用

-(void)onSocketDidDisconnect:(ASyncSocket *)sock;

當socket由于或沒有錯誤而斷開連接抡诞,如果你想要在斷開連接后release socket穷蛹,在此方法工作,而在onSocket:willDisconnectWithError 釋放則不安全

-(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket;

當產(chǎn)生一個socket去處理連接時調(diào)用昼汗,此方法會返回 線程上的run-loop 的新的socket和其應(yīng)處理的委托肴熏,如果省略,則使用[NSRunLoop cunrrentRunLoop]

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

-(void)onSocket:(AsyncSocket *)sock didConnectToHost :(NSString *)host port:(UINt16)port;

當socket連接正準備讀和寫的時候調(diào)用顷窒,host屬性是一個IP地址蛙吏,而不是一個DNS 名稱

-(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long) tag;

當socket已完成所要求的數(shù)據(jù)讀入內(nèi)存時調(diào)用,如果有錯誤則不調(diào)用

-(void)onSocket:(Asyncsocket *)sock didReadPartialDataOfLength:(NSUInteger)partiaLength tag:(long)tag;

當一個socket讀取數(shù)據(jù)鞋吉,但尚未完成讀操作的時候調(diào)用鸦做,如果使用 readToData: or readToLength: 方法 會發(fā)生,可以被用來更新進度條等東西

-(void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag;

當一個socket已完成請求數(shù)據(jù)的寫入時候調(diào)用

-(void)onSocket:(AsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag;

當一個socket寫入一些數(shù)據(jù),但還沒有完成整個寫入時調(diào)用谓着,它可以用來更新進度條等東西

-(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag elapsed:(NSTimeInterval)exapsed bytesDone:(NSUInteger)length

使用讀操作已超時但還沒完成時調(diào)用泼诱,此方法允許隨意延遲超時,如果返回一個正的時間間隔赊锚,讀取的超時將有一定量的擴展治筒,如果不實現(xiàn)這個方法屉栓,或會像往常一樣返回一個負的時間間隔,elapsed參數(shù)是? 原超時的總和耸袜,加上先前通過這種方法添加的任何補充友多, length參數(shù)是 讀操作到目前為止已讀取的字節(jié)數(shù), 注意堤框,如果返回正數(shù)的話域滥,這個方法可能被一個單獨的讀取多次調(diào)用

-(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutWriteWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length;

如果一個寫操作已達到其超時但還沒完成時調(diào)用,同上

-(void)onSocketDidSecure:(AsyncSocket *)sock;

在socket成功完成ssl/tls協(xié)商時調(diào)用胰锌,此方法除非你使用提供startTLS方法時候才調(diào)用骗绕,

如果ssl/tls是無效的證書,socket將會立即關(guān)閉资昧,onSocket:willDisconnectWithError:代理方法竟會與特定的ssl錯誤代碼一起調(diào)用

-(BOOL)canSafelySetDelegate

用來查看在改變它之前酬土,是否帶有與當前的委托有懸而未決的業(yè)務(wù)(讀/寫)。當然格带,應(yīng)在安全連接或接受委托之前改變委托

一旦接收或連接方法之一被調(diào)用撤缴,AsyncSocket實例會被鎖定,其他接收/連接方法在沒有先斷開socket不會被調(diào)用

如果嘗試失敗或超時叽唱,這些方法要么返回NO 要么調(diào)用 onSocket:willDisconnectWithError: 或 onSockedDidDisconnect

當傳入的連接被接受屈呕,AsyncSocket調(diào)用多個委托方法。這些方法按照時間順序排列:

1.onSocket:didAcceptNewSocket:

2.onSocket:wantsRunLoopForNewSocket:

3. onSocketWillConnect:

你的服務(wù)器的代碼將需要保留公認的socket(如果要接受它)棺亭,最好的地方是要做到這一點可能在onSocket:didAcceptNewSocket:方法

在讀和寫流已經(jīng)為新接受的socket設(shè)置虎眨,onSocket:didConnectToHost:port 方法將在適當?shù)倪\行循環(huán)調(diào)用

多線程注意,如果要想通過實施onSocket:wantsRunLoopForNewSocket:镶摘,移動另一個新接受的socket去到另一個循環(huán)的socket嗽桩。然后,應(yīng)該在調(diào)用讀和寫或者startTLS方法前凄敢,等待直到onSocket:didConnectToHost:port:方法碌冶。否則讀和寫時間原定于不正確的runloop,混亂可能會隨之而來

-(BOOL)acceptOnPort:(UInit16)port error:(NSError **)errPtr;

告訴socket開始聽取和接受制定端口上的連接涝缝,當一個連接到來的時候扑庞,AsyncSocket實例將調(diào)用各種委托方法,socket將聽取所有可用的接口(wifi,以太網(wǎng)等)

-(BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error :(NSError **)errPtr;

連接給定的主機和端口拒逮,主機hostname可以是域名或者是Ip地址

-(BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError *)errPtr;

連接到一個給定的地址罐氨,制定一個sockaddr結(jié)構(gòu)包裹住一個NSData對象,例如,NSData對象從NSNetService的地址方法返回,如果有一個現(xiàn)有的sockaddr結(jié)構(gòu)滩援,可以將它轉(zhuǎn)換到一個NSData對象栅隐,像這樣:

struct sockaddr sa? -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len];

struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len];

-(void)disconnect;

立即斷開,任何未處理的讀或?qū)懚紝⒈粊G棄

如果socket還沒有斷開,在這個方法返回之前约啊,onSocketDidDisconnect 委托方法將會被立即調(diào)用

注意推薦釋放AsyncSocket實例的方式:

[asyncSocket setDelegate:nil];

[asyncSocket disconnect];

[asyncSocket release];

-(void)disconnectAfterReading;

在已經(jīng)完成了所有懸而未決的讀取時 斷開,在調(diào)用之后,讀取和寫入方法將無用,socket將斷開 即使仍有待寫入

- (NSString *)connectedHost;

- (UInt16)connectedPort;

- (NSString *)localHost;

- (UInt16)localPort;

返回本地和遠程主機和端口給連接的socket佣赖,如果沒有連接會返回nil或0,主機將會是一個IP地址

-(NSData *)connectedAddress

-(NSData *)localAddresss

返回本地和遠程的地址給連接的socket恰矩,指定一個socketaddr結(jié)構(gòu)包裹在一個NSData對象

readData和writeData方法不會是block(它們是異步的)

當讀完成 onSocket:didReadData:withTag: 委托方法時調(diào)用

當寫完成 onSocket:didWriteDataWithTag: 委托方法時調(diào)用

可以選擇任何讀/寫操作的超時設(shè)置(為了不超時,使用負時間間隔憎蛤。)

如果讀/寫操作超時外傅,相應(yīng)的 onSocket:shouldTimeout...委托方法被調(diào)用去選擇性地允許我們?nèi)パ娱L超時

超時后,onSocket:willDisconnectWithError: 方法被調(diào)用,緊接著是 onSocketDidDisconnect

tag是為了方便俩檬,可以使用它作為數(shù)組的索引萎胰、步數(shù)、state id 棚辽、指針等

-(void)readDataWithTimeout:(NSTimeInterval)tiemout tag:(long)tag;

讀取socket上第一次成為可用的字節(jié),如果timeout值是負數(shù)的技竟,讀操作將不使用timeout

- (void)readDataWithTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInterger)offset tag:(long)tag;

讀取socket上第一次成為可用的字節(jié)

字節(jié)將被追加到給定的字節(jié)緩沖區(qū),從給定的偏移量開始

如果需要屈藐,給定的緩沖區(qū)大小將會自動增加

如果timeout值是負數(shù)的榔组,讀操作將不使用timeout

如果緩沖區(qū)為空,socket會為我們創(chuàng)建一個緩沖區(qū)

如果bufferOffset是大于給定的緩沖區(qū)的長度联逻,該方法將無用搓扯,委托將不會被調(diào)用

如果你傳遞一個緩沖區(qū),當AsyncSocket在使用它的時候你不能以任何方式改變它

完成之后包归,onSocket:didReadData:withTag 返回的數(shù)據(jù)將是一個給定的緩沖區(qū)的子集

也就是說锨推,它將會被引用到被追加的給定的緩沖區(qū)的字節(jié)

-(void)readDataToLength:(NSUInterger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag;

讀取給定的字節(jié)數(shù),如果length為0公壤,方法將無用换可,委托將不會被調(diào)用

-(void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)tiemout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;

讀取給定的字節(jié)數(shù),在給定的偏移開始,字節(jié)將被追加到給定的字節(jié)緩沖區(qū)

-(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;

讀取字節(jié)直到(包括)傳入的作為分隔的"data"參數(shù)

如果傳遞0或者0長度的數(shù)據(jù)境钟,"data"參數(shù)锦担,該方法將無用,委托將不會被調(diào)用

從socket讀取一行慨削,使用"data"參數(shù)作為行的分隔符 (如HTTP的CRLF)

注意洞渔,此方法不是字符集,因此缚态,如果一個分隔符出現(xiàn)磁椒,它自然可以作為進行編碼的一部分,讀取將提前結(jié)束

-(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;

讀取字節(jié)直到(包括)傳入的作為分隔的“data”參數(shù)玫芦,在給定的偏移量開始浆熔,字節(jié)將被追加到給定的字節(jié)緩沖區(qū)。

從socket讀取一行桥帆,使用"data"參數(shù)作為行的分隔符(如HTTP的CRLF)

-(void)writeData:(NSData *)data withTimeout:(NSTimeInterval) timeout tag:(long)tag;

將data寫入socket医增,當完成的時候委托被調(diào)用

- (float)progressOfReadReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;

- (float)progressOfWriteReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;

返回當前讀或?qū)懙倪M度慎皱,從0.0 到 1.0 或者 如果沒有讀/寫的時候返回Nan(使用isNan來檢查)

tag、done叶骨、total如果不為空的話茫多,它們將會被填補

- (void)startTLS:(NSDictionary *)tlsSettings;

確保使用ssl/tls連接

這方法可被隨時調(diào)用,tls握手將會發(fā)生在所有懸而未決的讀/寫完成之后忽刽。這緊跟著一個發(fā)送依賴 StartTLS消息的協(xié)議選項天揖,在排隊升級到TLS的同一時間,而不必等待寫入完成跪帝。在這個方法被調(diào)用后,任何讀寫計劃 將會發(fā)生在安全鏈接

對于可能的keys和TLS設(shè)置的值是有據(jù)可查的

一些可能的keys是:

* - kCFStreamSSLLevel

* - kCFStreamSSLAllowsExpiredCertificates

* - kCFStreamSSLAllowsExpiredRoots

* - kCFStreamSSLAllowsAnyRoot

* - kCFStreamSSLValidatesCertificateChain

* - kCFStreamSSLPeerName

* - kCFStreamSSLCertificates

* - kCFStreamSSLIsServer

如果你傳遞空或者空字典今膊,將使用默認的字典

默認設(shè)置將檢查以確保由簽署可信的第三方證書機構(gòu)和沒有過期的遠程連接的證書

然而,它不會驗證證書上的名字伞剑,除非你給它一個名字斑唬,通過kCFStreamSSLPeerName鍵去驗證

這對安全的影響是重要的理解

想象一下你正試圖創(chuàng)建一個到MySecureServer.com的安全連接,但因為一個被攻擊的DNS服務(wù)器纸泄,所以你的socket被定向到MaliciousServer.com

如果你只是使用默認設(shè)置赖钞,MaliciousServer.com 有一個有效的證書

默認設(shè)置將無法監(jiān)測到任何問題,因為證書是有效的

在這個特殊的情況下聘裁,要妥善保護你的連接雪营,應(yīng)設(shè)置kCFStreamSSLPeerName性質(zhì)為MySecureServer.com.

如果事前你不知道對等的名字的遠程主機(例如,你不確認它是domain.com" or "www.domain.com")衡便,那么你可以使用默認設(shè)置來驗證證書献起,然后在獲得驗證的發(fā)行后使用X509Certificate類來驗證,X509Certificate類的CocoaAsyncSocket開源項目的一部分

-(void)enablePrebuffering

對于處理readDataToData請求,數(shù)據(jù)是必須從socket以小增量的方式讀取出來的

性能通過允許AsyncSocket去一次性讀大塊的數(shù)據(jù)和存儲任何一個小的內(nèi)部緩沖區(qū)溢出的東西來大大提高

這被稱為預(yù)緩沖镣陕,就好像一些數(shù)據(jù)在你要求它之前就可能被讀取出來

如果你經(jīng)常使用readDataToData谴餐,使用預(yù)緩沖會有更好的性能,尤其是在iphone上

默認的預(yù)緩沖狀態(tài)是由DEFAULT_PREBUFFERING 定義控制的呆抑,強烈建議設(shè)置其為yes

這方法存在一些預(yù)緩沖需要一些不可預(yù)見的原因被默認禁用的情況岂嗓,這時,這種方法存在允許當就緒時鹊碍,可輕松啟用預(yù)緩沖

-(BOOL)moveToRunLoop:(NSRunLoop *)runLoop;

當你創(chuàng)建一個AsyncSocket厌殉,它被添加到當前線程runloop

對于手動創(chuàng)建的socket,在線程上你打算使用它侈咕,它是最容易簡單的創(chuàng)建的線程上的socket

當一個新的socket被接受公罕,委托方法 onSocket:wantsRunLoopForNewSocket 會被調(diào)用 允許你在一個單獨的線程上放置socket,這個工作最好結(jié)合在同一個線程池設(shè)計

如果耀销,但是楼眷,在一個單獨的線程上,在之后的時間,你需要移動一個socket罐柳,這個方法可以用來完成任務(wù)

此方法必須從 當前運行的 線程/runloop 的socket 調(diào)用

注意:此方法調(diào)用后掌腰,所有進一步的方法應(yīng)該從給定的runloop上調(diào)用這個對象

此外,所有委托調(diào)用將會發(fā)送到給定的runloop

- (BOOL)setRunLoopModes:(NSArray *)runLoopModes;

- (BOOL)addRunLoopMode:(NSString *)runLoopMode;

- (BOOL)removeRunLoopMode:(NSString *)runLoopMode;

允許你配置 socket 使用的 運行循環(huán)模式

運行循環(huán)模式設(shè)置默認是NSRunLoopCommonModes

如果你想你的socket 在其他模式下繼續(xù)操作张吉,你可能需要添加模式 NSModalPanelRunLoopMode 或者 NSEventTrackingRunLoopMode ,或者你可能只想使用 NSRunLoopCommonModes

可接受的socket將自動 繼承相同的運行循環(huán)模式就像偵聽socket

注意:NSRunLoopCommonModes 定義在10.5辅斟,對于之前的版本可使用 kCFRunLoopCommonModes

-(NSArray *)runLoopModes

返回當前正在運行的循環(huán)模式的AsyncSocket實例, run loop modes的默認設(shè)置是NSDefaultRunLoopMode

-(NSData *)unreadData;

一個錯誤的事件芦拿,在 onSocket:willDisconnectWithError: 將會被調(diào)用 去讀取留在socket上的任何數(shù)據(jù)

+ (NSData *)CRLFData;?? // 0x0D0A

各方法的解析

-(void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err;

發(fā)生錯誤,socket關(guān)閉查邢,可以在call-back過程調(diào)用"unreadData"去取得socket的最后的數(shù)據(jù)字節(jié)蔗崎,當連接的時候,該委托方法在??? onSocket:didAcceptNewSocket: 或者 onSocket:didConnectToHost: 之前調(diào)用

發(fā)生錯誤扰藕,socket關(guān)閉缓苛,可以在call-back過程調(diào)用"unreadData"去取得socket的最后的數(shù)據(jù)字節(jié),當連接的時候邓深,該委托方法在??? onSocket:didAcceptNewSocket: 或者 onSocket:didConnectToHost: 之前調(diào)用

-(void)onSocketDidDisconnect:(ASyncSocket *)sock;

當socket由于或沒有錯誤而斷開連接未桥,如果你想要在斷開連接后release socket,在此方法工作芥备,而在onSocket:willDisconnectWithError 釋放則不安全

-(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket;

當產(chǎn)生一個socket去處理連接時調(diào)用冬耿,此方法會返回 線程上的run-loop 的新的socket和其應(yīng)處理的委托,如果省略萌壳,則使用[NSRunLoop cunrrentRunLoop]

當產(chǎn)生一個socket去處理連接時調(diào)用亦镶,此方法會返回 線程上的run-loop 的新的socket和其應(yīng)處理的委托,如果省略袱瓮,則使用[NSRunLoop cunrrentRunLoop]

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

-(void)onSocket:(AsyncSocket *)sock didConnectToHost :(NSString *)host port:(UINt16)port;

當socket連接正準備讀和寫的時候調(diào)用缤骨,host屬性是一個IP地址,而不是一個DNS 名稱

-(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long) tag;

當socket已完成所要求的數(shù)據(jù)讀入內(nèi)存時調(diào)用尺借,如果有錯誤則不調(diào)用

-(void)onSocket:(Asyncsocket *)sock didReadPartialDataOfLength:(NSUInteger)partiaLength tag:(long)tag;

當一個socket讀取數(shù)據(jù)绊起,但尚未完成讀操作的時候調(diào)用,如果使用 readToData: or readToLength: 方法 會發(fā)生,可以被用來更新進度條等東西

-(void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag;

當一個socket已完成請求數(shù)據(jù)的寫入時候調(diào)用

-(void)onSocket:(AsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag;

當一個socket寫入一些數(shù)據(jù)燎斩,但還沒有完成整個寫入時調(diào)用虱歪,它可以用來更新進度條等東西

-(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag elapsed:(NSTimeInterval)exapsed bytesDone:(NSUInteger)length

使用讀操作已超時但還沒完成時調(diào)用,此方法允許隨意延遲超時瘫里,如果返回一個正的時間間隔实蔽,讀取的超時將有一定量的擴展,如果不實現(xiàn)這個方法谨读,或會像往常一樣返回一個負的時間間隔局装,elapsed參數(shù)是? 原超時的總和,加上先前通過這種方法添加的任何補充, length參數(shù)是 讀操作到目前為止已讀取的字節(jié)數(shù)铐尚, 注意拨脉,如果返回正數(shù)的話,這個方法可能被一個單獨的讀取多次調(diào)用

-(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutWriteWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length;

如果一個寫操作已達到其超時但還沒完成時調(diào)用宣增,同上

-(void)onSocketDidSecure:(AsyncSocket *)sock;

在socket成功完成ssl/tls協(xié)商時調(diào)用玫膀,此方法除非你使用提供startTLS方法時候才調(diào)用,

如果ssl/tls是無效的證書爹脾,socket將會立即關(guān)閉帖旨,onSocket:willDisconnectWithError:代理方法竟會與特定的ssl錯誤代碼一起調(diào)用

-(BOOL)canSafelySetDelegate

用來查看在改變它之前,是否帶有與當前的委托有懸而未決的業(yè)務(wù)(讀/寫)灵妨。當然解阅,應(yīng)在安全連接或接受委托之前改變委托

一旦接收或連接方法之一被調(diào)用,AsyncSocket實例會被鎖定泌霍,其他接收/連接方法在沒有先斷開socket不會被調(diào)用

如果嘗試失敗或超時货抄,這些方法要么返回NO 要么調(diào)用 onSocket:willDisconnectWithError: 或 onSockedDidDisconnect

當傳入的連接被接受,AsyncSocket調(diào)用多個委托方法朱转。這些方法按照時間順序排列:

1.onSocket:didAcceptNewSocket:

2.onSocket:wantsRunLoopForNewSocket:

3. onSocketWillConnect:

你的服務(wù)器的代碼將需要保留公認的socket(如果要接受它)蟹地,最好的地方是要做到這一點可能在onSocket:didAcceptNewSocket:方法

在讀和寫流已經(jīng)為新接受的socket設(shè)置,onSocket:didConnectToHost:port 方法將在適當?shù)倪\行循環(huán)調(diào)用

多線程注意藤为,如果要想通過實施onSocket:wantsRunLoopForNewSocket:怪与,移動另一個新接受的socket去到另一個循環(huán)的socket。然后缅疟,應(yīng)該在調(diào)用讀和寫或者startTLS方法前琼梆,等待直到onSocket:didConnectToHost:port:方法。否則讀和寫時間原定于不正確的runloop窿吩,混亂可能會隨之而來

-(BOOL)acceptOnPort:(UInit16)port error:(NSError **)errPtr;

告訴socket開始聽取和接受制定端口上的連接茎杂,當一個連接到來的時候,AsyncSocket實例將調(diào)用各種委托方法纫雁,socket將聽取所有可用的接口(wifi,以太網(wǎng)等)

-(BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error :(NSError **)errPtr;

連接給定的主機和端口煌往,主機hostname可以是域名或者是Ip地址

-(BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError *)errPtr;

連接到一個給定的地址,制定一個sockaddr結(jié)構(gòu)包裹住一個NSData對象,例如轧邪,NSData對象從NSNetService的地址方法返回,如果有一個現(xiàn)有的sockaddr結(jié)構(gòu)刽脖,可以將它轉(zhuǎn)換到一個NSData對象,像這樣:

struct sockaddr sa? -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len];

struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len];

-(void)disconnect;

立即斷開忌愚,任何未處理的讀或?qū)懚紝⒈粊G棄

如果socket還沒有斷開曲管,在這個方法返回之前,onSocketDidDisconnect 委托方法將會被立即調(diào)用

注意推薦釋放AsyncSocket實例的方式:

[asyncSocket setDelegate:nil];

[asyncSocket disconnect];

[asyncSocket release];

-(void)disconnectAfterReading;

在已經(jīng)完成了所有懸而未決的讀取時 斷開,在調(diào)用之后硕糊,讀取和寫入方法將無用,socket將斷開 即使仍有待寫入

- (NSString *)connectedHost;

- (UInt16)connectedPort;

- (NSString *)localHost;

- (UInt16)localPort;

返回本地和遠程主機和端口給連接的socket院水,如果沒有連接會返回nil或0,主機將會是一個IP地址

-(NSData *)connectedAddress

-(NSData *)localAddresss

返回本地和遠程的地址給連接的socket腊徙,指定一個socketaddr結(jié)構(gòu)包裹在一個NSData對象

readData和writeData方法不會是block(它們是異步的)

當讀完成 onSocket:didReadData:withTag: 委托方法時調(diào)用

當寫完成 onSocket:didWriteDataWithTag: 委托方法時調(diào)用

可以選擇任何讀/寫操作的超時設(shè)置(為了不超時,使用負時間間隔檬某。)

如果讀/寫操作超時撬腾,相應(yīng)的 onSocket:shouldTimeout...委托方法被調(diào)用去選擇性地允許我們?nèi)パ娱L超時

超時后,onSocket:willDisconnectWithError: 方法被調(diào)用,緊接著是 onSocketDidDisconnect

tag是為了方便恢恼,可以使用它作為數(shù)組的索引民傻、步數(shù)、state id 场斑、指針等

-(void)readDataWithTimeout:(NSTimeInterval)tiemout tag:(long)tag;

讀取socket上第一次成為可用的字節(jié),如果timeout值是負數(shù)的漓踢,讀操作將不使用timeout

- (void)readDataWithTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInterger)offset tag:(long)tag;

讀取socket上第一次成為可用的字節(jié)

字節(jié)將被追加到給定的字節(jié)緩沖區(qū),從給定的偏移量開始

如果需要漏隐,給定的緩沖區(qū)大小將會自動增加

如果timeout值是負數(shù)的彭雾,讀操作將不使用timeout

如果緩沖區(qū)為空,socket會為我們創(chuàng)建一個緩沖區(qū)

如果bufferOffset是大于給定的緩沖區(qū)的長度锁保,該方法將無用,委托將不會被調(diào)用

如果你傳遞一個緩沖區(qū)半沽,當AsyncSocket在使用它的時候你不能以任何方式改變它

完成之后爽柒,onSocket:didReadData:withTag 返回的數(shù)據(jù)將是一個給定的緩沖區(qū)的子集

也就是說,它將會被引用到被追加的給定的緩沖區(qū)的字節(jié)

-(void)readDataToLength:(NSUInterger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag;

讀取給定的字節(jié)數(shù)者填,如果length為0浩村,方法將無用,委托將不會被調(diào)用

-(void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)tiemout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;

讀取給定的字節(jié)數(shù),在給定的偏移開始占哟,字節(jié)將被追加到給定的字節(jié)緩沖區(qū)

-(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;

讀取字節(jié)直到(包括)傳入的作為分隔的"data"參數(shù)

如果傳遞0或者0長度的數(shù)據(jù)铐姚,"data"參數(shù)缀蹄,該方法將無用,委托將不會被調(diào)用

從socket讀取一行夭谤,使用"data"參數(shù)作為行的分隔符 (如HTTP的CRLF)

注意恳不,此方法不是字符集卵惦,因此,如果一個分隔符出現(xiàn),它自然可以作為進行編碼的一部分庸疾,讀取將提前結(jié)束

-(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag;

讀取字節(jié)直到(包括)傳入的作為分隔的“data”參數(shù)乍楚,在給定的偏移量開始,字節(jié)將被追加到給定的字節(jié)緩沖區(qū)届慈。

從socket讀取一行徒溪,使用"data"參數(shù)作為行的分隔符(如HTTP的CRLF)

-(void)writeData:(NSData *)data withTimeout:(NSTimeInterval) timeout tag:(long)tag;

將data寫入socket忿偷,當完成的時候委托被調(diào)用

- (float)progressOfReadReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;

- (float)progressOfWriteReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total;

返回當前讀或?qū)懙倪M度,從0.0 到 1.0 或者 如果沒有讀/寫的時候返回Nan(使用isNan來檢查)

tag臊泌、done鲤桥、total如果不為空的話,它們將會被填補

- (void)startTLS:(NSDictionary *)tlsSettings;

確保使用ssl/tls連接

這方法可被隨時調(diào)用渠概,tls握手將會發(fā)生在所有懸而未決的讀/寫完成之后茶凳。這緊跟著一個發(fā)送依賴 StartTLS消息的協(xié)議選項,在排隊升級到TLS的同一時間播揪,而不必等待寫入完成贮喧。在這個方法被調(diào)用后,任何讀寫計劃 將會發(fā)生在安全鏈接

對于可能的keys和TLS設(shè)置的值是有據(jù)可查的

一些可能的keys是:

* - kCFStreamSSLLevel

* - kCFStreamSSLAllowsExpiredCertificates

* - kCFStreamSSLAllowsExpiredRoots

* - kCFStreamSSLAllowsAnyRoot

* - kCFStreamSSLValidatesCertificateChain

* - kCFStreamSSLPeerName

* - kCFStreamSSLCertificates

* - kCFStreamSSLIsServer

如果你傳遞空或者空字典,將使用默認的字典

默認設(shè)置將檢查以確保由簽署可信的第三方證書機構(gòu)和沒有過期的遠程連接的證書

然而猪狈,它不會驗證證書上的名字箱沦,除非你給它一個名字,通過kCFStreamSSLPeerName鍵去驗證

這對安全的影響是重要的理解

想象一下你正試圖創(chuàng)建一個到MySecureServer.com的安全連接雇庙,但因為一個被攻擊的DNS服務(wù)器谓形,所以你的socket被定向到MaliciousServer.com

如果你只是使用默認設(shè)置,MaliciousServer.com 有一個有效的證書

默認設(shè)置將無法監(jiān)測到任何問題疆前,因為證書是有效的

在這個特殊的情況下寒跳,要妥善保護你的連接,應(yīng)設(shè)置kCFStreamSSLPeerName性質(zhì)為MySecureServer.com.

如果事前你不知道對等的名字的遠程主機(例如峡继,你不確認它是domain.com" or "www.domain.com"),那么你可以使用默認設(shè)置來驗證證書匈挖,然后在獲得驗證的發(fā)行后使用X509Certificate類來驗證,X509Certificate類的CocoaAsyncSocket開源項目的一部分

-(void)enablePrebuffering

對于處理readDataToData請求碾牌,數(shù)據(jù)是必須從socket以小增量的方式讀取出來的

性能通過允許AsyncSocket去一次性讀大塊的數(shù)據(jù)和存儲任何一個小的內(nèi)部緩沖區(qū)溢出的東西來大大提高

這被稱為預(yù)緩沖,就好像一些數(shù)據(jù)在你要求它之前就可能被讀取出來

如果你經(jīng)常使用readDataToData儡循,使用預(yù)緩沖會有更好的性能舶吗,尤其是在iphone上

默認的預(yù)緩沖狀態(tài)是由DEFAULT_PREBUFFERING 定義控制的,強烈建議設(shè)置其為yes

這方法存在一些預(yù)緩沖需要一些不可預(yù)見的原因被默認禁用的情況择膝,這時誓琼,這種方法存在允許當就緒時,可輕松啟用預(yù)緩沖

-(BOOL)moveToRunLoop:(NSRunLoop *)runLoop;

當你創(chuàng)建一個AsyncSocket肴捉,它被添加到當前線程runloop

對于手動創(chuàng)建的socket腹侣,在線程上你打算使用它,它是最容易簡單的創(chuàng)建的線程上的socket

當一個新的socket被接受齿穗,委托方法 onSocket:wantsRunLoopForNewSocket 會被調(diào)用 允許你在一個單獨的線程上放置socket傲隶,這個工作最好結(jié)合在同一個線程池設(shè)計

如果,但是窃页,在一個單獨的線程上跺株,在之后的時間复濒,你需要移動一個socket,這個方法可以用來完成任務(wù)

此方法必須從 當前運行的 線程/runloop 的socket 調(diào)用

注意:此方法調(diào)用后乒省,所有進一步的方法應(yīng)該從給定的runloop上調(diào)用這個對象

此外巧颈,所有委托調(diào)用將會發(fā)送到給定的runloop

- (BOOL)setRunLoopModes:(NSArray *)runLoopModes;

- (BOOL)addRunLoopMode:(NSString *)runLoopMode;

- (BOOL)removeRunLoopMode:(NSString *)runLoopMode;

允許你配置 socket 使用的 運行循環(huán)模式

運行循環(huán)模式設(shè)置默認是NSRunLoopCommonModes

如果你想你的socket 在其他模式下繼續(xù)操作,你可能需要添加模式 NSModalPanelRunLoopMode 或者 NSEventTrackingRunLoopMode ,或者你可能只想使用 NSRunLoopCommonModes

可接受的socket將自動 繼承相同的運行循環(huán)模式就像偵聽socket

注意:NSRunLoopCommonModes 定義在10.5袖扛,對于之前的版本可使用 kCFRunLoopCommonModes

-(NSArray *)runLoopModes

返回當前正在運行的循環(huán)模式的AsyncSocket實例砸泛, run loop modes的默認設(shè)置是NSDefaultRunLoopMode

-(NSData *)unreadData;

一個錯誤的事件,在 onSocket:willDisconnectWithError: 將會被調(diào)用 去讀取留在socket上的任何數(shù)據(jù)

+ (NSData *)CRLFData;?? // 0x0D0A

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末攻锰,一起剝皮案震驚了整個濱河市晾嘶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌娶吞,老刑警劉巖垒迂,帶你破解...
    沈念sama閱讀 206,013評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異妒蛇,居然都是意外死亡机断,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評論 2 382
  • 文/潘曉璐 我一進店門绣夺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吏奸,“玉大人,你說我怎么就攤上這事陶耍》芪担” “怎么了?”我有些...
    開封第一講書人閱讀 152,370評論 0 342
  • 文/不壞的土叔 我叫張陵烈钞,是天一觀的道長泊碑。 經(jīng)常有香客問我,道長毯欣,這世上最難降的妖魔是什么馒过? 我笑而不...
    開封第一講書人閱讀 55,168評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮酗钞,結(jié)果婚禮上腹忽,老公的妹妹穿的比我還像新娘。我一直安慰自己砚作,他們只是感情好窘奏,可當我...
    茶點故事閱讀 64,153評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著葫录,像睡著了一般蔼夜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上压昼,一...
    開封第一講書人閱讀 48,954評論 1 283
  • 那天求冷,我揣著相機與錄音瘤运,去河邊找鬼。 笑死匠题,一個胖子當著我的面吹牛拯坟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播韭山,決...
    沈念sama閱讀 38,271評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼郁季,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了钱磅?” 一聲冷哼從身側(cè)響起梦裂,我...
    開封第一講書人閱讀 36,916評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎盖淡,沒想到半個月后年柠,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,382評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,877評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了戚哎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 37,989評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡掀抹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出心俗,到底是詐尸還是另有隱情傲武,我是刑警寧澤,帶...
    沈念sama閱讀 33,624評論 4 322
  • 正文 年R本政府宣布城榛,位于F島的核電站揪利,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏吠谢。R本人自食惡果不足惜土童,卻給世界環(huán)境...
    茶點故事閱讀 39,209評論 3 307
  • 文/蒙蒙 一诗茎、第九天 我趴在偏房一處隱蔽的房頂上張望工坊。 院中可真熱鬧,春花似錦敢订、人聲如沸王污。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽昭齐。三九已至,卻和暖如春矾柜,著一層夾襖步出監(jiān)牢的瞬間阱驾,已是汗流浹背就谜。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留里覆,地道東北人丧荐。 一個月前我還...
    沈念sama閱讀 45,401評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像喧枷,于是被迫代替她去往敵國和親虹统。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,700評論 2 345

推薦閱讀更多精彩內(nèi)容