GCDAsyncSocket源碼分析

類分析

  • GCDAsyncSocket

  • 狀態(tài)的枚舉

enum GCDAsyncUdpSocketFlags
{
    kDidCreateSockets        = 1 <<  0,  // If set, the sockets have been created.
    kDidBind                 = 1 <<  1,  // If set, bind has been called.
    kConnecting              = 1 <<  2,  // If set, a connection attempt is in progress.
    kDidConnect              = 1 <<  3,  // If set, socket is connected.
    kReceiveOnce             = 1 <<  4,  // If set, one-at-a-time receive is enabled
    kReceiveContinuous       = 1 <<  5,  // If set, continuous receive is enabled
    kIPv4Deactivated         = 1 <<  6,  // If set, socket4 was closed due to bind or connect on IPv6.
    kIPv6Deactivated         = 1 <<  7,  // If set, socket6 was closed due to bind or connect on IPv4.
    kSend4SourceSuspended    = 1 <<  8,  // If set, send4Source is suspended.
    kSend6SourceSuspended    = 1 <<  9,  // If set, send6Source is suspended.
    kReceive4SourceSuspended = 1 << 10,  // If set, receive4Source is suspended.
    kReceive6SourceSuspended = 1 << 11,  // If set, receive6Source is suspended.
    kSock4CanAcceptBytes     = 1 << 12,  // If set, we know socket4 can accept bytes. If unset, it's unknown.
    kSock6CanAcceptBytes     = 1 << 13,  // If set, we know socket6 can accept bytes. If unset, it's unknown.
    kForbidSendReceive       = 1 << 14,  // If set, no new send or receive operations are allowed to be queued.
    kCloseAfterSends         = 1 << 15,  // If set, close as soon as no more sends are queued.
    kFlipFlop                = 1 << 16,  // Used to alternate between IPv4 and IPv6 sockets.
#if TARGET_OS_IPHONE
    kAddedStreamListener     = 1 << 17,  // If set, CFStreams have been added to listener thread
#endif
};
  • Param
#if __has_feature(objc_arc_weak)
    __weak id delegate;
#else
    __unsafe_unretained id delegate;
#endif
    dispatch_queue_t delegateQueue;
    
    GCDAsyncUdpSocketReceiveFilterBlock receiveFilterBlock;
    dispatch_queue_t receiveFilterQueue;
    BOOL receiveFilterAsync;
    
    GCDAsyncUdpSocketSendFilterBlock sendFilterBlock;
    dispatch_queue_t sendFilterQueue;
    BOOL sendFilterAsync;
    
    uint32_t flags;//當前類的狀態(tài)
    uint16_t config;
    
    uint16_t max4ReceiveSize;//最大接收數(shù)據(jù)包的大小
    uint32_t max6ReceiveSize;
    
    int socket4FD;//socket文件描述符
    int socket6FD;
    
    dispatch_queue_t socketQueue;//socket隊列
    
    dispatch_source_t send4Source;//發(fā)送的source
    dispatch_source_t send6Source;
    dispatch_source_t receive4Source;
    dispatch_source_t receive6Source;
    dispatch_source_t sendTimer;//發(fā)送的定時器
    
    GCDAsyncUdpSendPacket *currentSend;//當前發(fā)送的數(shù)據(jù)包
    NSMutableArray *sendQueue;//發(fā)送隊列
    
    unsigned long socket4FDBytesAvailable;//
    unsigned long socket6FDBytesAvailable;
    
    uint32_t pendingFilterOperations;
    
    NSData   *cachedLocalAddress4;
    NSString *cachedLocalHost4;
    uint16_t  cachedLocalPort4;
    
    NSData   *cachedLocalAddress6;
    NSString *cachedLocalHost6;
    uint16_t  cachedLocalPort6;
    
    NSData   *cachedConnectedAddress;
    NSString *cachedConnectedHost;
    uint16_t  cachedConnectedPort;
    int       cachedConnectedFamily;

    void *IsOnSocketQueueOrTargetQueueKey;//socketQueue的標識符    
    
#if TARGET_OS_IPHONE
    CFStreamClientContext streamContext;
    CFReadStreamRef readStream4;
    CFReadStreamRef readStream6;
    CFWriteStreamRef writeStream4;
    CFWriteStreamRef writeStream6;
#endif
    
    id userData;
  • GCDAsyncUdpSendPacket
    NSData *buffer;//發(fā)送的數(shù)據(jù)
    NSTimeInterval timeout;//超時的時間
    long tag;//發(fā)送數(shù)據(jù)包的tag
    
    BOOL resolveInProgress;//解決中
    BOOL filterInProgress;//過濾中
    
    NSArray *resolvedAddresses;//被解決的地址
    NSError *resolveError;//解決出現(xiàn)的錯誤
    
    NSData *address;//地址
    int addressFamily;

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

  - (void)sendData:(NSData *)data toHost:(NSString *)host port:(uint16_t)port withTimeout:(NSTimeInterval)timeout tag:(long)tag;

這個方法中實例化了發(fā)送包趁蕊,并把host和port轉化為地址(參見getaddrinfo()函數(shù))

GCDAsyncSocket發(fā)送消息方法詳解

<>中的是方法名,有些方法名沒有寫全愁溜,所以配合代碼食用更佳熄驼。


<SendData>
創(chuàng)建GCDAsyncUdpSendPacket
host轉address
做檢查操作   <doPreSend>
把packet裝入sendQueue中
執(zhí)行出列操作  <maybeDequeueSend>

<maybeDequeueSend>
創(chuàng)建socket 執(zhí)行 <createSockets>
出列當前sendQueue中的packet并作為currentSend
特殊狀態(tài)處理GCDAsyncUdpSpecialPacket
錯誤處理
做預處理郭蕉,檢查包    執(zhí)行 <doPreSend>

<doPreSend>
有連接
如果currentSend正在進行其他操作,返回錯誤
如果沒有丁鹉,給currentSend賦值
無連接
packet進行其他操作妒潭,等待
遇上錯誤,返回
沒地址的處理
    兩種連接最后總要給currentSend的address和addressFamily屬性賦值揣钦。
等待的處理:暫停 source
錯誤處理
Filter處理
沒有Filter情況直接執(zhí)行      <doSend>

<doSend>
有連接
發(fā)送方法為result=send()
無連接
發(fā)送方法為result=sendto() 參數(shù)中包含地址參數(shù)
根據(jù)result來判斷是否等待
錯誤處理是等待還是返回錯誤
等待情況的處理(沒有足夠空間)
當當前沒有不能接收數(shù)據(jù)的時候(kSock4CanAcceptBytes)說明有空間了杜耙,所以要重新開始source
    設置超時相應
        超時執(zhí)行    <maybeDequeueSend>
錯誤處理
正常情況
    繼續(xù)從sendQueue中拿出packet來繼續(xù)搞事 執(zhí)行   <maybeDequeueSend>

<createSockets>
判斷IPv4|6是否可用
創(chuàng)建socket 執(zhí)行         <createSocket4>

<createSocket4>
創(chuàng)建socket的文件描述符
設置發(fā)送和接收source       執(zhí)行  <setupSendAndReceiveSourcesForSocket4>

<setupSendAndReceiveSourcesForSocket4>
創(chuàng)建source
設置event
    send source
    出錯處理
    執(zhí)行  <suspendSend4Source>
    無錯處理
    執(zhí)行  <doSend>

    receive source
    出錯處理
    無錯處理
    執(zhí)行  <doReceive>
設置cancel

<doReceive>
通過flag判斷是否該暫停或者重啟receive source
計算是否該用IPv6|4拂盯;分有連接和無連接的情況
執(zhí)行socket IO佑女;使用result=recvfrom()函數(shù)接收數(shù)據(jù) 包括data
根據(jù)result判斷是否等待,錯誤處理,然后執(zhí)行代理方法通知接收到了數(shù)據(jù)谈竿。filter的操作团驱。
對等待和錯誤處理的值進行處理。
無錯處理
flag&kReceiveContinuous 繼續(xù)接收
接收一次    執(zhí)行      <doReceive>

例子:
一個packet過來
先進行地址轉換resolveInProgress = yes
進行轉換的時候空凸,同時進行出列操作嚎花,然后執(zhí)行doPreSend
doPreSend中resolveInProgress會導致source暫停
然后當?shù)刂忿D換進行完畢的時候,會再次調用doPreSend方法
這時候就會直接去調用doSend方法
調用sendto()方法

doPreSend的時候會因為currentSend正在干別的事情而暫停source

這個過程沒有講filter的相關內容呀洲。

預計理解dispatch_source/time的相關內容紊选。
c的函數(shù)庫的那些方法和結構體作為了解內容。
還有代碼組織方式道逗。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末兵罢,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子滓窍,更是在濱河造成了極大的恐慌卖词,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,331評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吏夯,死亡現(xiàn)場離奇詭異此蜈,居然都是意外死亡即横,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,372評論 3 398
  • 文/潘曉璐 我一進店門裆赵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來东囚,“玉大人,你說我怎么就攤上這事战授∫吃澹” “怎么了?”我有些...
    開封第一講書人閱讀 167,755評論 0 360
  • 文/不壞的土叔 我叫張陵陈醒,是天一觀的道長惕橙。 經常有香客問我瞧甩,道長钉跷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,528評論 1 296
  • 正文 為了忘掉前任肚逸,我火速辦了婚禮爷辙,結果婚禮上,老公的妹妹穿的比我還像新娘朦促。我一直安慰自己膝晾,他們只是感情好,可當我...
    茶點故事閱讀 68,526評論 6 397
  • 文/花漫 我一把揭開白布务冕。 她就那樣靜靜地躺著血当,像睡著了一般。 火紅的嫁衣襯著肌膚如雪禀忆。 梳的紋絲不亂的頭發(fā)上臊旭,一...
    開封第一講書人閱讀 52,166評論 1 308
  • 那天,我揣著相機與錄音箩退,去河邊找鬼离熏。 笑死,一個胖子當著我的面吹牛戴涝,可吹牛的內容都是我干的滋戳。 我是一名探鬼主播,決...
    沈念sama閱讀 40,768評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼啥刻,長吁一口氣:“原來是場噩夢啊……” “哼奸鸯!你這毒婦竟也來了?” 一聲冷哼從身側響起可帽,我...
    開封第一講書人閱讀 39,664評論 0 276
  • 序言:老撾萬榮一對情侶失蹤府喳,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蘑拯,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體钝满,經...
    沈念sama閱讀 46,205評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡兜粘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,290評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了弯蚜。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片孔轴。...
    茶點故事閱讀 40,435評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖碎捺,靈堂內的尸體忽然破棺而出路鹰,到底是詐尸還是另有隱情,我是刑警寧澤收厨,帶...
    沈念sama閱讀 36,126評論 5 349
  • 正文 年R本政府宣布晋柱,位于F島的核電站,受9級特大地震影響诵叁,放射性物質發(fā)生泄漏雁竞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,804評論 3 333
  • 文/蒙蒙 一拧额、第九天 我趴在偏房一處隱蔽的房頂上張望碑诉。 院中可真熱鬧,春花似錦侥锦、人聲如沸进栽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,276評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽快毛。三九已至,卻和暖如春番挺,著一層夾襖步出監(jiān)牢的瞬間唠帝,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工建芙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留没隘,地道東北人。 一個月前我還...
    沈念sama閱讀 48,818評論 3 376
  • 正文 我出身青樓禁荸,卻偏偏與公主長得像右蒲,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子赶熟,可洞房花燭夜當晚...
    茶點故事閱讀 45,442評論 2 359

推薦閱讀更多精彩內容

  • //Clojure入門教程: Clojure – Functional Programming for the J...
    葡萄喃喃囈語閱讀 3,680評論 0 7
  • 多線程瑰妄、特別是NSOperation 和 GCD 的內部原理。運行時機制的原理和運用場景映砖。SDWebImage的原...
    LZM輪回閱讀 2,009評論 0 12
  • 史上最全的iOS面試題及答案 iOS面試小貼士———————————————回答好下面的足夠了----------...
    Style_偉閱讀 2,359評論 0 35
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理间坐,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,693評論 18 139
  • ———————————————回答好下面的足夠了---------------------------------...
    恒愛DE問候閱讀 1,720評論 0 4