GCDAsyncSocket_Reference

原文:https://github.com/robbiehanson/CocoaAsyncSocket/wiki/Reference_GCDAsyncSocket

GCDAsyncSocket 是基于 Grand Central Dispatch 構(gòu)建的 TCP 套接字網(wǎng)絡(luò)庫。該項(xiàng)目還包含一個(gè)基于 RunLoop 的版本,以及 UDP 套接字庫。

CocoaAsyncSocket 項(xiàng)目是一個(gè)成熟的開源框架,自 2003 年以來一直存在。因此,它已經(jīng)受益于廣泛的網(wǎng)絡(luò)開發(fā)人員,他們已經(jīng)提交了代碼或建議的功能。該項(xiàng)目的目標(biāo)是創(chuàng)建強(qiáng)大而易用的套接字庫。

GCDAsyncSocket 的特性包括:

  • 原生 Objective-C 實(shí)現(xiàn),完全獨(dú)立在一個(gè)類之中。
    不需要與 socket 或 stream 混在一起。這個(gè)類為您處理所有事情
  • 完整的 delegate 支持
    錯(cuò)誤、連接、讀完成、寫完成、進(jìn)度和斷開連接都會(huì)調(diào)用委托方法
  • 隊(duì)列和非阻塞讀寫,帶有可選的超時(shí)選項(xiàng)。
    你告訴它讀什么或?qū)懯裁矗鼤?huì)為你處理一切事情。在自動(dòng)處理的流中自動(dòng)排隊(duì)、緩沖和搜索終止序列
  • 自動(dòng)接收 socket。
    啟動(dòng)一個(gè) socket 服務(wù),告訴它接受連接,它會(huì)為每個(gè)連接調(diào)用自己的新實(shí)例
  • 支持 IPv4 及 IPv6 上的 TCP 流。
    自動(dòng)連接到 IPv4 或 IPv6 主機(jī)。使用這個(gè)類的一個(gè)實(shí)例自動(dòng)接受通過 IPv4 和 IPv6 傳入的連接。不用再擔(dān)心多個(gè) socket
  • 支持 TLS/SSL。
    只使用一個(gè)方法調(diào)用就可以輕松地保護(hù)您的 socket。支持客戶端和服務(wù)端 socket。
  • 完全基于 GCD 和線程安全
    它完全在它自己的 GCD dispatch_queue 中運(yùn)行,并且是完全線程安全的。此外,委托方法全部異步調(diào)用到您選擇的 dispatch_queue 上。這意味著它可以并行執(zhí)行你的 socket 代碼和委托/處理代碼。

GCDAsyncSocket 的一個(gè)比較強(qiáng)大的功能是它的隊(duì)列架構(gòu)。這允許您在方便的時(shí)候控制套接字,而不是當(dāng)套接字告訴您它準(zhǔn)備好了。舉幾個(gè)例子。

// 開始異步連接。
// 下面的方法將立即返回。
// 并且委托方法socket:didConnectToHost:port:將在連接完成后被調(diào)用。
[asyncSocket connectToHost:host onPort:port error:nil];

// 此時(shí)此刻,套接字還沒有連接。
// 它剛剛開始異步連接嘗試。
// 但 AsyncSocket 的設(shè)計(jì)是為了讓你更容易地進(jìn)行套接字編程。
// 如果你方便的話,你可以自由地開始讀/寫。
// 所以我們現(xiàn)在要開始讀取消息頭的請求。
// 讀取請求會(huì)自動(dòng)排隊(duì)。
// 當(dāng)套接字連接后,這個(gè)讀取請求將自動(dòng)被去掉隊(duì)列并執(zhí)行。
[asyncSocket readDataToLength:LENGTH_HEADER withTimeout:TIMEOUT_NONE tag:TAG_HEADER];

除此之外,你還可以根據(jù)方便調(diào)用多個(gè)讀寫請求。

// 開始異步寫操作
[asyncSocket writeData:msgHeader withTimeout:TIMEOUT_NONE tag:TAG_HEADER];

// 我們不需要等待寫完后再開始下一次寫
[asyncSocket writeData:msgBody withTimeout:TIMEOUT_NONE tag:TAG_BODY];
// 開始異步讀取操作。
// 讀取并忽略歡迎信息。
[asyncSocket readDataToData:msgSeparator withTimeout:TIMEOUT_NONE tag:TAG_WELCOME];

// 我們不必等待該次讀取完成后再開始下一次讀取。
// 讀取服務(wù)器能力。
[asyncSocket readDataToData:msgSeparator withTimeout:TIMEOUT_NONE tag:TAG_CAPABILITIES];

隊(duì)列式架構(gòu)甚至延伸到SSL/TLS支持!

// Send startTLS confirmation ACK.
// Remember this is an asynchronous operation.
[asyncSocket writeData:ack withTimeout:TIMEOUT_NONE tag:TAG_ACK];

// We don't have to wait for the write to complete before invoking startTLS.
// The socket will automatically queue the operation, and wait for previous reads/writes to complete.
// Once that has happened, the upgrade to SSL/TLS will automatically start.
[asyncSocket startTLS:tlsSettings];

// Again, we don't have to wait for the security handshakes to complete.
// We can immediately queue our next operation if it's convenient for us.
// So we can start reading the next request from the client.
// This read will occur over a secure connection.
[asyncSocket readDataToData:msgSeparator withTimeout:TIMEOUT_NONE tag:TAG_MSG];

超時(shí)(Timeouts)是大多數(shù)操作的可選參數(shù)。

除此之外,你可能已經(jīng)注意到了標(biāo)簽參數(shù)。讀/寫操作中傳遞的標(biāo)簽會(huì)在讀/寫操作完成后通過委托方法傳回給你。它不會(huì)通過套接字發(fā)送或從套接字中讀取。它的設(shè)計(jì)是為了幫助簡化您的委托方法中的代碼。例如,你的委托方法可能是這樣的。

#define TAG_WELCOME 10
#define TAG_CAPABILITIES 11
#define TAG_MSG 12

... 

- (void)socket:(AsyncSocket *)sender didReadData:(NSData *)data withTag:(long)tag
{
    if (tag == TAG_WELCOME)
    {
        // Ignore welcome message
    }
    else if (tag == TAG_CAPABILITIES)
    {
        [self processCapabilities:data];
    }
    else if (tag == TAG_MSG)
    {
        [self processMessage:data];
    }
}

GCDAsyncSocket是線程安全的。

License

這個(gè)類是在公共領(lǐng)域。

最初由 Robbie Hanson 在 2010 年第三季度創(chuàng)建。

由 Deusty Designs 和 Mac 開發(fā)社區(qū)更新和維護(hù)。

Reference

...


創(chuàng)建 socket 方法:

/** 
 * GCDAsyncSocket 使用標(biāo)準(zhǔn)的委托模式。
 * 但會(huì)在給定的委托隊(duì)列上執(zhí)行所有的委托回調(diào)。
 * 這可以允許最大的并發(fā)性,同時(shí)提供簡單的線程安全。
 * 
 * 您必須先設(shè)置一個(gè)委托和委托隊(duì)列,然后再嘗試使用 socket,否則你會(huì)得到一個(gè)錯(cuò)誤。
 * 
 * socket 隊(duì)列是可選的
 * 如果傳遞 NULL,GCDAsyncSocket 將自動(dòng)創(chuàng)建自己的 socket 隊(duì)列。
 * 如果你選擇自己提供一個(gè) socket 隊(duì)列,那么該 socket 隊(duì)列必須不是一個(gè)并發(fā)隊(duì)列。
 * 如果選擇提供一個(gè) socket 隊(duì)列,并且 socket 隊(duì)列有一個(gè)配置的 target 隊(duì)列,那么GCDAsyncSocket 將自動(dòng)創(chuàng)建自己的套接字隊(duì)列。
 * 那么請看 markSocketQueueTargetQueue 方法的討論。
 * 
 * 委托隊(duì)列和 socket 隊(duì)列可以選擇使用相同的隊(duì)列。
 **/
- (instancetype)init;
- (instancetype)initWithSocketQueue:(nullable dispatch_queue_t)sq;
- (instancetype)initWithDelegate:(nullable id<GCDAsyncSocketDelegate>)aDelegate delegateQueue:(nullable dispatch_queue_t)dq;
- (instancetype)initWithDelegate:(nullable id<GCDAsyncSocketDelegate>)aDelegate delegateQueue:(nullable dispatch_queue_t)dq socketQueue:(nullable dispatch_queue_t)sq NS_DESIGNATED_INITIALIZER;

當(dāng) socket 斷開連接時(shí)被調(diào)用:

/**
 * 當(dāng) socket 斷開連接時(shí)調(diào)用,可能有錯(cuò)誤,可能沒有錯(cuò)誤。
 * 
 * 如果你調(diào)用 disconnect 方法,而 socket 還沒有被斷開。
 * 那么對該委托方法的調(diào)用將被列入委托人隊(duì)列(delegateQueue)。
 * 在斷開方法返回之前。
 * 
 * 注意:如果 GCDAsyncSocket 實(shí)例在連接時(shí)被 deallocated,
 * 而同時(shí) delegate 沒有被 deallocated,那么這個(gè)方法也會(huì)被調(diào)用。
 * 但回調(diào)方法中的 sock 參數(shù)將是nil。(它必須是 nil,因?yàn)樗呀?jīng)不可用了)。
 * 這種情況一般很少見,但如果寫這樣的代碼是可能的。
 * 
 * asyncSocket = nil; // 我隱含地?cái)嚅_了 socket 連接。
 * 
 * 在這種情況下,最好事先將 delegate  作廢,比如這樣。
 * 
 * asyncSocket.delegate = nil; // 不要調(diào)用我的 delegate 方法。
 * asyncSocket = nil; // 我隱含地?cái)嚅_了 socket 連接。
 * 
 * 當(dāng)然,這取決于你的狀態(tài)機(jī)是如何配置的。
**/
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(nullable NSError *)err;

讀取數(shù)據(jù)的幾個(gè)方法:

//讀取數(shù)據(jù),有數(shù)據(jù)就會(huì)觸發(fā)代理
- (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag;
// 讀取指定長度的數(shù)據(jù),才會(huì)觸發(fā)代理
- (void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag;
// 讀取到指定 data 邊界,才會(huì)觸發(fā)代理
- (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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