移動平台下的Socket幾個問題

2022-03-19 15:34:09 字數 2071 閱讀 1076

在頁遊時代,使用flash actionscript 3.0進行開發,as3提供比較簡單和健全的socket api。到了手遊時代,基於tcp的socket程式設計遇到了一些棘手的問題。通常情況下手遊都要支援至少二大主流平台:android、ios,二者共存,暫時沒有跡象表現哪一方會沒落。

頁遊跑在瀏覽器裡,所有的連線成功、失敗等操作,都可以通過addeventlistener進行監聽,很方便,一般也不存在頻繁掉線的情況。而手遊,因為手機的便攜性決定了它的移動性,既然是可移動的那就會一定會面臨網路不穩定的情況。

client與server通訊如果使用tcp邏輯會比較簡單一些,但存在一些問題,這個問題在移動平台下暴露的比較明顯。qq客戶端使用的是udp而非tcp,主要原因是因為網路的不穩定性。而tcp和udp主要區別是什麼呢?其實就是長連線與短連線的區別

長連線是比較消耗資源的,但是通常情況下,一方斷了另一方會較為及時的收到訊息,業務邏輯上是比較簡單和及時的。

基於tcp的socket網路程式設計,如果想跨平台,通常都使用c/c++進行封裝,這樣**層面至少是統一了。但移動裝置上面臨的主要問題是頻繁的掉線,android好一點,ios其實是比較麻煩的。下面列一下在android、ios裝置上home、電源鍵對網路的影響:

平台home鍵切後(網路狀態)

電源鍵(網路狀態)

androidyy

iosyn

其它的2g/3g/4g/wifi之間的相互切換,也是比較麻煩,必須要重連了(因為客戶端的ip已經發生變化了)。

電源鍵按下時,ios就鎖屏了。socket就斷掉了,但server端並不會收到client掉線。問題來了,不是說tcp是長連線嗎,我一端掉了那另一端應該收到斷開的訊息啊,嗯,理論上是這樣子的,協議也是這麼規定的,但要先注意這樣乙個問題:

tcp連線使用的是三次握手

tcp斷開使用的是四次握手

連線使用三次握手,這個不多說了,主要原因是為了保證二端都能確認連線已經建立(syn、ack)。而斷開為什麼是四次?因為socket是雙工(雙向通訊),相當於存在二條通訊的線路,一條用於接收,一條用於傳送。一方主動關閉時(寫信道被關閉了,但此時讀通道還是正常的),它會傳送fin,另一端收到時會響應fin+1(表示我收到你的關閉請求啦~),然後另一端處理完自己的邏輯後,告訴發起請求關閉的一方,我同意了你的關閉請求(不會再向你傳送資料啦~),此時發起關閉的一方的讀通道才是正常被關閉了。發起請求關閉的一方會在2msl(報文最長生命週期的兩倍 maximum segment lifetime)後釋放掉它所占用的埠(連線記錄此時才會被清除)。

所以,你會發現哇,原來關閉也是需要確認的。假設伺服器突然斷電了,客戶端是不知道伺服器端已經無法連線了的,還會認為可以傳送資料給伺服器端。通常都是使用心跳包進行檢測來雙方的連線是否還存在。

我嘗試過在cocos2dx使用libuv來實現網路通訊,感覺非同步寫起來確實過於繁瑣。libuv採用非同步**的寫法,所有的**函式必須是static的。通常一款遊戲是有二個socket長連線的:遊戲主邏輯、聊天伺服器,好在libuv支援**引數裡「夾帶自定義引數」,倒也問題不大。不過我遇到一件奇葩的事情是,在三星gti9000 android 2.3.6系統上,將遊戲切入後台,網路狀態由2g變成wifi,不**socket,呼叫傳送之後也沒有觸發關閉**方法,其它能借用到的android裝置都測試過,沒什麼問題了。wifi切到2g/3g,後台切換至前台後立馬觸發關閉的**函式。

後端處理是這樣的,建立socket時會隨機生成乙個金鑰串,當客戶端斷開連線時,拿這個金鑰串向伺服器進行驗證,但是伺服器驗證時有個特殊的判定,如果請求生成金鑰串的客戶端ip與重連時的客戶端ip不一致,則認為是非法請求。也就是說2g切換至wifi時,ip變了,伺服器其實是直接將連線斷開了,但為什麼沒觸發關閉的**函式,這個或許是那個android系統版本的bug吧

後來想的辦法有二個:

1、針對android平台,記錄連線時的網路型別,然後切換至前台時再獲取網路型別,如果發現二次的網路型別不一致就提示需要重新登入遊戲了;

2、記錄建立連線時的ip位址,當切換至前台再獲取ip,如果這二個ip不致,也認為是需要重登入遊戲了,因為無論你拿什麼金鑰串都將無法再登入遊戲,伺服器認為這個請求是非法的;

幾個移動平台比較

現在的移動平台主要有j2me symbian brew smartphone2002 pocketpc。pocketpc想成為主流不大可能,所以 ms推出 smartphone 但smartphone 現在情況不明。如果brew 能被聯通採用,那必定會有大發展,但聯通也能可能選 j2me symbi...

Emacs linux 平台下的神器

emacs,請大家去網上google 一下,本人應用有近三年,略懂皮毛,但沒有她的時候,我會第乙個找到她,然後才開始工作 無論是在linux下,還是不得已情況下用w.emacs 的使用步驟 1.用新立德安裝emacs 23,有好多版本,選最新的,有好多外掛程式,選了解的,逐漸追加 2.emacs 最...

DOCKER Windows平台下的安裝

重新開啟docker,呼叫映象,然後virtualbox啟動,這個時候在你本機的網路介面卡裡可以看到oracle虛擬機器裡的linux的網路,這種網路是dhcp協議分配的,當然你也可以開啟virtualbox 檢視 網絡卡1配置的連線方式是nat 網路位址轉換 這種大意舉個例子,本來你在學校裡上電腦...