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