iOS基礎之網絡編程問題集

前言

現階段工作需要和網絡編程打交道,用的是第三方的CocoaAsyncSocket,雖然github上有文檔但感覺真的不是非常詳細,很多情況還是有很多比較迷惑的地方。這篇文章將記錄我在學習應用過程中的一些迷惑點,希望能給別人幫助的同時給予自己幫助

正文

issue No1. GCDAsyncSocketDelegate下的socketDidDisconnect
完整的方法- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(nullable NSError *)err
已掌握:

  1. 這個方法是GCDAsyncSocketDelegate代理下的,由這個代理自動掉用(什麼時候調用)
  2. 如果不想觸發這個代理方法,只需要設置self.delegate = nil 就行了
  3. 連着的socket斷開,把wifi斷了以後,會自動掉用這個代理方法
  4. 物理網絡斷開,客戶端和服務器的socket是不知道斷開的,需要作處理(不知道CocoaAsyncSocket怎麼處理的)
  5. 物理網絡斷開,客戶端和服務器的socket其實沒有斷開,需要close(4次揮手)纔會斷開雙方socket
  6. 當網絡斷開,還是可以通過socket來向外寫數據的動作(只不過這時候寫不出去),當寫不出去(使用socket
  7. 通信不成功)的時候會觸發這個回調函數socketDidDisconnect

困難點

  1. 什麼時候掉用這個代理方法?
    先看一下文檔的解釋

If you call the disconnect method, and the socket wasn’t already disconnected, then an invocation of this delegate method will be enqueued on the delegateQueue before the disconnect method returns.
Note: If the GCDAsyncSocket instance is deallocated while it is still connected, and the delegate is not also deallocated, then this method will be invoked, but the sock parameter will be nil. (It must necessarily be nil since it is no longer available.) This is a generally rare, but is possible if one writes code like this:
asyncSocket = nil; // I’m implicitly disconnecting the socket
In this case it may preferrable to nil the delegate beforehand, like this:
asyncSocket.delegate = nil; // Don’t invoke my delegate method asyncSocket = nil; // I’m implicitly disconnecting the socket
Of course, this depends on how your state machine is configured.

如果你調用了disconnect方法,並且這個socket還沒有斷開,那麼在disconnect方法返回之前會將這個代理方法(socketDidDisconnect)放到delegateQueue隊列中。


ignore: disconnect會將這個代理方法放到隊列中,等斷開完畢的時候觸發。看這個網絡庫很多都是放到隊列裏面的,比如writeData放到隊列裏面,readDataToLength放到隊列裏面,到後面滿足某個情況觸發


當這個socket還連接的時候,如果這個GCDAsyncSocket實例對象釋放了,並且這個socket的delegate還沒釋放,那麼這個方法會執行(在socket還連接的時候,我將socket=nil;釋放對象,那麼socket都釋放了,socket.delegate 爲什麼還沒釋放,從而觸發這個方法?),但是這個方法參數中的socket值是nil(它必須是nil,如果不再有效)。這是比較罕見的,但是它是有可能的,比如有人寫成下面的代碼
asyncSocket = nil; // I’m implicitly disconnecting the socket
這種情況它可能更喜歡事先將這個delegate設置爲nil,像下面一樣
asyncSocket.delegate = nil; //執行條件滿足的情況下,也不要去執行我的代理方法。 asyncSocket = nil; //我暗中斷開這個socket
當然,這是依靠你當前情況的電腦配置是怎麼樣的


ignore: 連接還在,代理還在,將socke實例對象釋放了,這個方法將會掉用。我很想知道wifi關閉以後爲什麼會掉用這個代理方法


issue No.2 wifi斷開以後,客戶端和服務器的socket是否已斷開
已掌握

  1. 客戶端有一個socket用來和服務器通信,服務器也有一個soket和該客戶端通信(客戶端socket連接服務器時產生)
  2. 我重新連上網,是否可以繼續通信
  3. 心跳包發送消息給服務器,讓服務器明白這個socket還是有效的,當在一定時間內沒收到心跳包消息,就將socket給斷了

issue No.3 客戶端同一個socket,有兩個地方不停斷髮數據,那麼在本機接收數據是如何的

已掌握

  1. 長連接接收數據,它的數據都是放到棧裏面的(放到buffer裏面的,服務器迴應的數據是放一起的),可以通過readDataToLength去分隔開來,也可以如http協議一樣適用\n來分隔
  2. 長連接是可靠的,有序的,會重發的,會避免堵塞的功能

問題點
1. 程序裏面使用socket不斷向服務器傳送數據並顯示進度條,另外一個地方需要用這個socket不斷向服務器發送請求獲取狀態。 這樣同一時間內socket在棧裏面是什麼樣子的,如果接收的數據包是固定長度的,我依次讀下來會不會讀到兩者結合的數據(A的head和B的body數據結合在一起了),我實際工作碰到的情況,兩者向服務器發送的數據速度不一樣,到時一方進度條停止(沒有從棧裏面讀到屬於進度條的數據,讀到的都是狀態的數據,所以進度條停止)。

未完待續

發佈了88 篇原創文章 · 獲贊 29 · 訪問量 29萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章