<iOS 實(shí)踐>關(guān)于在 iOS Socket 的一些記錄(雜記)

首先需要了解 Socket 的一些基本知識, 然后看了一下官方的 API.

這次由于要構(gòu)建一個調(diào)試工具, 先選用的是 robbiehanson/CocoaAsyncSocket 這個框架, 先對而言上手很快, 且使用簡單.

要實(shí)現(xiàn)的需求是要在手機(jī)端搭建一個 Socket 接收端, 同時也需要發(fā)送數(shù)據(jù).

但是第一個坎就沒有過去, 當(dāng)在手機(jī)上(iOS 11.2.2)實(shí)現(xiàn)服務(wù)端時, 無法接收外界傳入的數(shù)據(jù)(使用 UDP 情況下, TCP 下亦然).

為了驗(yàn)證, 故切換為 TCP, 然后用 MAC 實(shí)現(xiàn)一個服務(wù)端, 手機(jī)連接進(jìn)去一切正常, 情況如下:

把服務(wù)端放到 MAC 上, 完全相同的 Socket 服務(wù)端代碼條件下, 指定了如下圖的 APP 功能, 則可以正常連接(TCP):


image.png

這里是手機(jī)端的輸出:

嘗試連接
已連接到: 192.168.199.127:9002

這里是 MAC 電腦上的輸出:

已啟動監(jiān)聽
已監(jiān)聽到連接并建立連接.
newSocket's localHost: 192.168.199.127
newSocket's connectedHost: 192.168.199.116

如果上面的勾勾不打的話, 會提示綁定端口錯誤.

但是在 iOS 工程上, 真沒有找到和這個勾勾類似的東西...

再去參考一下 swisspol/GCDWebServer, 為什么它可以讓服務(wù)器在手機(jī)上運(yùn)行起來呢, 而且可以指定端口? 證明并非是 IP 的關(guān)系. 所以這里就進(jìn)入到它的源碼里面去看看.

發(fā)現(xiàn)兩個的實(shí)現(xiàn)原理都不一樣, GCDWebServer 是基于 bonjour 的.

莫非是 iOS 直接就禁止了監(jiān)聽外界的 Socket 請求? 找了網(wǎng)上很久也沒找到可以在 iOS 上構(gòu)建 Socket 服務(wù)端到底可行否? 且完全沒有找到任何地方有在 iOS 上建立 Socket 服務(wù)端的案例, 所以最好的辦法還是從頭開始仔細(xì)看看官方文檔...

好吧, 網(wǎng)上有說用 multi peer connectivity framework 來實(shí)現(xiàn)的, 下面就來看看. 有時候一條路走不通, 就換種思路繼續(xù)做唄...

先看了一下這篇文章, 里面說到它是Bonjour 的繼承者, 然后看了一下內(nèi)容, 貌似還是只有蘋果平臺可用...

文末提到 Websocket, 可用嘗試一下...

但最終發(fā)現(xiàn)全部的例子中, 如果用 TCP 的情況下, 都是把手機(jī)作為客戶端的. 如果用 UDP 的話手機(jī)和其他地方就是兩個對等的點(diǎn)了.

故繼續(xù)看官方文檔, 先看 Networking Overview 啟發(fā)一下思路, 然后是 Networking Programming Topics...

參考官文里面的一句:

There are only two APIs that provide the ability to listen for incoming network connections: the Core Foundation socket API and the POSIX (BSD) socket API. Higher-level APIs cannot be used for accepting incoming connections.

即目前只有兩套 API 提供了監(jiān)聽網(wǎng)絡(luò)連接請求的能力, 一套是 Core Foundation socket API, 另外一套是 POSIX 的 Socket API. 高層的 API 無法被用來 accepting 進(jìn)入的連接.

use NSStream for remote connections and CFSocket for listening

使用 NSStream 來建立遠(yuǎn)程連接, 而用 CFSocket 來監(jiān)聽及 accepting 進(jìn)入的連接.(詳見上述Networking Programming Topics 中的 Do Not Use NSSocketPort (OS X) or NSFileHandle for General Socket Communication)

之前直接建立了一個可工作的客戶端, 下面就來跟著官文建立一個可監(jiān)聽外界連接請求的服務(wù)端.

文檔中需要的 <sys/socket.h> 在 swift 4 中默認(rèn)就已經(jīng)引入進(jìn)去了的, 貌似 <netinet/in.h> 也是一樣.

在 swift 官網(wǎng)上有一句說的是:

BSD sockets are a common pain point for Swift interoperability. Swift 3.0 exposes the difficultly in doing this correcly. Fortunately, Quinn “The Eskimo!” has provided these helpful wrappers.

下面提供了一個 Socket 擴(kuò)展, 詳見這個鏈接, 便于使用.

但為何兩個 iPhone 之間的 Socket 通信這么蛋疼? 在蘋果官方論壇找到了這樣一個問答: iOS 10.2 socket issue, 這里說到了兩個 iPhone 之間的 Socket 通信受阻并非是由系統(tǒng)造成的, 可能是由于 wifi 等外部原因造成的(比如本地的 wifi 阻止了 iOS 設(shè)備間的 STA TO STA 通信, STA 即 station, 它相當(dāng)于 wifi 中的客戶端設(shè)備), 在里面推薦了一篇關(guān)于入門文章Wi-Fi Fundamentals.

由于要徹底解決 wifi 導(dǎo)致的通信受阻問題, 就需要首先了解 wifi 中的一些東西, 根據(jù)上面的文章, 慢慢看.

術(shù)語表:

  • STA (station) : wifi 中的客戶端設(shè)備
  • AP (access point): 指的是運(yùn)行 Wi-Fi 網(wǎng)絡(luò)的硬件設(shè)備. 關(guān)于這里定義的 Wifi 網(wǎng)絡(luò)的詳細(xì)信息在后面會講.
  • SSID (Service Set Identifier): It’s the user-visible network identifier string that you see throughout the system.
  • BSSID (Basic Service Set Identifier): This defines a single Wi-Fi network at the Wi-Fi level. It’s identified by the MAC address of the AP, something that’s generally not user visible.

wifi 實(shí)現(xiàn)了如下兩類廣播:

  • Unicasts
  • Broadcasts(Multicasts)

不過最后最主要的還是在文章末尾提到一個檢測 STA--->AP, AP--->STA 的包傳輸跟蹤方法, 詳見Getting a Packet Trace.

這里是一些 MAC 上可用的網(wǎng)絡(luò)調(diào)試工具列表.

先把 iPhone 的整個網(wǎng)絡(luò)棧映射到 MAC 上, 然后通過網(wǎng)絡(luò)調(diào)試工具來查看通信內(nèi)容:

The RVI represents the entire networking stack of the iOS device

具體操作:

  1. 用 USB 連接手機(jī)和 MAC 電腦.
  2. 為設(shè)備創(chuàng)建一個 RVI(remote virtual interface, 遠(yuǎn)程虛擬接口, iOS 5 以上版本才有) , 通過 RVI, 可以在 MAC 上使用抓包工具來追蹤 iPhone 上的網(wǎng)絡(luò)通信.
    # 使用如下命令可以查看當(dāng)前所有的網(wǎng)絡(luò)接口:
    ifconfig -l
    # 這個命令執(zhí)行后顯示如下
    lo0 gif0 stf0 en0 en1 p2p0 fw0 ppp0 utun0
    # 獲取設(shè)備的 UUID(在 itunes 里就看得到), 然后用如下命令建立 RVI, 命令參數(shù)即UUID:
    rvictl -s 74bd53c647548234ddcef0ee3abee616005051ed
    # 此時再用 ifconfig -l 查看的話, 會發(fā)現(xiàn)多了一個網(wǎng)絡(luò)接口, 多出來的 rvi0 就是新建的:
    ifconfig -l
    lo0 gif0 stf0 en0 en1 p2p0 fw0 ppp0 utun0 rvi0
    
  3. 有了上述的接口名稱 rvi0, 就可以通過抓包工具對該接口進(jìn)行抓包(下面只是演示):
    sudo tcpdump -i rvi0 -A
    
  4. 如果是想移除 RVI, 則執(zhí)行如下命令:
    # 其中參數(shù)值是設(shè)備的 UUID
    rvictl -x 74bd53c647548234ddcef0ee3abee616005051ed
    

另外有一個 CPA 工具, 來分析看包到底到了手機(jī)端沒有.

tcpdump 也是個好東西, 可以學(xué)學(xué)它的用法, 具體可以參考這篇官文.

下面的測試使用的是如下命令來執(zhí)行的 tcpdump:

# ip 地址為想要監(jiān)聽的host, 從該 host 發(fā)送的包, 或發(fā)向該 host 的包都會被抓取.
sudo tcpdump host 192.168.199.116 -i rvi1

但在測試的時候有一個問題:
兩臺手機(jī), 一臺 iPhone6P, 一臺 iPhone 6, 然后在 Xcode 中寫了兩個示例工程, 一個工程只是通過
UDP 協(xié)議利用 Socket 發(fā)送數(shù)據(jù), 另外一個工程的作用是接收通過 UDP 協(xié)議發(fā)送的過來的數(shù)據(jù).

  1. 當(dāng)使用 6 來向 6P 發(fā)送數(shù)據(jù), 無法發(fā)送.
  2. 當(dāng)使用 6P 來向 6 發(fā)送數(shù)據(jù), 一切正常.
  3. 使用 tcpdump 查看, 實(shí)際上每次發(fā)送的時候數(shù)據(jù)包都是過去了的(抓取接收方的包是接收到了的, 發(fā)送方也是發(fā)送了的).

數(shù)據(jù)包在兩種情況下都是順利被發(fā)送和接收到了的, 但為什么一個手機(jī)在上層無法接收, 另外一個可以接收呢?

蘋果在 10.2 之后可能對網(wǎng)絡(luò)功能進(jìn)行了修改? 但兩個手機(jī)的系統(tǒng)都是 11.2.2 , 為什么同樣的發(fā)送和接收代碼, 在兩臺 iPhone 上面還會有不同的反應(yīng)?

上面遇到的問題就無法解答了, 望看到的朋友能夠給予幫助, 萬分感謝!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末心包,一起剝皮案震驚了整個濱河市雕憔,隨后出現(xiàn)的幾起案子硅急,更是在濱河造成了極大的恐慌笤成,老刑警劉巖瞬铸,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件诱渤,死亡現(xiàn)場離奇詭異病曾,居然都是意外死亡处面,警方通過查閱死者的電腦和手機(jī)如贷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門陷虎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人杠袱,你說我怎么就攤上這事尚猿。” “怎么了楣富?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵凿掂,是天一觀的道長。 經(jīng)常有香客問我纹蝴,道長庄萎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任骗灶,我火速辦了婚禮惨恭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘耙旦。我一直安慰自己脱羡,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布免都。 她就那樣靜靜地躺著锉罐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪绕娘。 梳的紋絲不亂的頭發(fā)上脓规,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機(jī)與錄音险领,去河邊找鬼侨舆。 笑死秒紧,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的挨下。 我是一名探鬼主播熔恢,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼臭笆!你這毒婦竟也來了叙淌?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤愁铺,失蹤者是張志新(化名)和其女友劉穎鹰霍,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體茵乱,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡茂洒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了似将。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片获黔。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖在验,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情堵未,我是刑警寧澤腋舌,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站渗蟹,受9級特大地震影響块饺,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜雌芽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一授艰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧世落,春花似錦淮腾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至武花,卻和暖如春圆凰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背体箕。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工专钉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留挑童,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓跃须,卻偏偏與公主長得像站叼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子回怜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355