Ⅰ android推送SDK(9)-TCP網路問題
主目錄見: Android高級進階知識(這是總目錄索引)
[written by 無心追求 ]
常
把Http和TCP連接服務做區分導致IM的TCP使用80埠連接進來的時候被誤
識別成是一個Http請求,所以就對IM的TCP數據流(TLV格式)進行解析導
致報錯返回了一個Http請求報錯的網頁的Html數據,具體返回的數據格式
客戶端列印是:
以上是客戶端TCP數據流read到100位元組列印出來的數據,是一個Http請求
失敗返回Http狀態碼為400的網頁Html數據
以上是tcpmp抓包信息,從抓包信息中可以得知返回的數據確實是一個
Http請求失敗的網頁,對比客戶端程序log列印是吻合的
式的數據,所以對read到的數據進行常規的TLV數據解析導致程序解析報錯
(數組越界):
客戶端發生數據解析報錯之後會認為當前接收到的數據已經不正確,同時
也會認為後面接續讀取的數據也將不正確,所以會把socket連接關閉重連
:
應該下調心跳周期,但是舊版(1.0.1Realease-1.0.6Realease版本)存在
不足,並沒有對此做過濾處理,所以會不斷的下調心跳
斷線後會馬上重連
接斷開的域名和埠再次嘗試重連,在重試重連失敗的時候才會去切換域
名或者埠,而遇到這種情況,每次嘗試重連TCP都能連接成功,連接成功
之後,數據解析失敗又把TCP連接斷開,然後再拿原來的域名和埠,再重
連,再斷開,如此陷入死循環,無法切換域名或者埠,斷線重連頻率很
高:
TCP連接IM伺服器gw.im.okii.com成功,連接埠為80
入的TCP數據為323個位元組
的數據進行解析
srcPos=2 dst.length=121 dstPos=0 length=121表示數據解析報錯,數組
越界
誤的識別成Http短連接
不下調心跳間隔,避免心跳誤下調,影響心跳探測的准確性
時間間隔遞增重連,避免頻繁的重連
一些常用的埠,例如8080,443,1000一下的埠等都不能使用,避免出
現類似的問題
和埠去再次連接IM伺服器導致無法跳出這個域名和埠連接造成的異常
,如果客戶端有成功切換域名或者埠,那麼遇到上述情況會立即切換到
8000埠,次數連接就會恢復正常
有上傳大數據的手錶分析來看全部都恢復正常使用
111.44.228.186這個地址(正確的應該是106.75.86.52),而被誤識別成
Http短鏈接,然後返回一個錯誤的網頁html數據,然後客戶端接收到數據
後解析報錯,導致頻繁的斷線重連和心跳下調
跳誤下調,重連頻繁,與香港的原因類似
gw.im.okii.com本地dns解析出來的ip為111.44.228.186,由此確認是被劫
持了
客戶端對接收到的TCP數據解析異常,數
組越界
客戶端在數據解析異常後斷線
連接斷開後心跳下調
Ⅱ Android-Socket
由於二者不屬於同一層面,所以本來是沒有可比性的。但隨著發展,默認的Http里封裝了下面幾層的使用,所以才會出現Socket & HTTP協議的對比:(主要是工作方式的不同):
Socket可理解為一種特殊的文件,在伺服器和客戶端各自維護一個文件,並使用SocketAPI函數對其進行文件操作。在建立連接打開後,可以向各自文件寫入內容供對方讀取或讀取對方內容,通信結束時關閉文件。在UNIX哲學中「一切皆文件」,文件的操作模式基本為「打開-讀寫-關閉」三大步驟,Socket其實就是這個模式的一個實現。
創建socket的時候,也可以指定不同的參數創建不同的socket描述符,socket函數的三個參數分別為:
當我們調用socket創建一個socket時,返回的socket描述字它存在於協議族(address family,AF_XXX)空間中,但沒有一個具體的地址。如果想要給它賦值一個地址,就必須調用bind()函數,否則就當調用connect()、listen()時系統會自動隨機分配一個埠。
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
函數的三個參數分別為:
如果作為一個伺服器,在調用socket()、bind()之後就會調用listen()來監聽這個socket,如果客戶端這時調用connect()發出連接請求,伺服器端就會接收到這個請求。
TCP伺服器端依次調用socket()、bind()、listen()之後,就會監聽指定的socket地址了。TCP客戶端依次調用socket()、connect()之後就想TCP伺服器發送了一個連接請求。TCP伺服器監聽到這個請求之後,就會調用accept()函數取接收請求,這樣連接就建立好了。之後就可以開始網路I/O操作了,即類同於普通文件的讀寫I/O操作。
注意:accept的第一個參數為伺服器的socket描述字,是伺服器開始調用socket()函數生成的,稱為監聽socket描述字;而accept函數返回的是已連接的socket描述字。一個伺服器通常通常僅僅只創建一個監聽socket描述字,它在該伺服器的生命周期內一直存在。內核為每個由伺服器進程接受的客戶連接創建了一個已連接socket描述字,當伺服器完成了對某個客戶的服務,相應的已連接socket描述字就被關閉。
萬事具備只欠東風,至此伺服器與客戶已經建立好連接了。可以調用網路I/O進行讀寫操作了,即實現了網咯中不同進程之間的通信!網路I/O操作有下面幾組:
read()/write()
recv()/send()
readv()/writev()
recvmsg()/sendmsg()
recvfrom()/sendto()
我推薦使用recvmsg()/sendmsg()函數,這兩個函數是最通用的I/O函數,實際上可以把上面的其它函數都替換成這兩個函數。
從圖中可以看出,當客戶端調用connect時,觸發了連接請求,向伺服器發送了SYN J包,這時connect進入阻塞狀態;伺服器監聽到連接請求,即收到SYN J包,調用accept函數接收請求向客戶端發送SYN K ,ACK J+1,這時accept進入阻塞狀態;客戶端收到伺服器的SYN K ,ACK J+1之後,這時connect返回,並對SYN K進行確認;伺服器收到ACK K+1時,accept返回,至此三次握手完畢,連接建立。
總結:客戶端的connect在三次握手的第二個次返回,而伺服器端的accept在三次握手的第三次返回。
某個應用進程首先調用close主動關閉連接,這時TCP發送一個FIN M;
另一端接收到FIN M之後,執行被動關閉,對這個FIN進行確認。它的接收也作為文件結束符傳遞給應用進程,因為FIN的接收意味著應用進程在相應的連接上再也接收不到額外數據;
一段時間之後,接收到文件結束符的應用進程調用close關閉它的socket。這導致它的TCP也發送一個FIN N;
接收到這個FIN的源發送端TCP對它進行確認。
這樣每個方向上都有一個FIN和ACK。
所謂短連接,即連接只保持在數據傳輸過程,請求發起,連接建立,數據返回,連接關閉。它適用於一些實時數據請求,配合輪詢來進行新舊數據的更替。
https://github.com/nuisanceless/MySocketDemo
https://github.com/xuuhaoo/OkSocket
Ⅲ Android網路請求知識(三)授權,TCP/IP,HTTPS建立過程
由身份或持有的令牌確認享有的許可權,登錄過程實質上的目的也是為了確認許可權。
Cookie是客戶端給伺服器用的,setCookie是伺服器給客戶端用的。cookie由伺服器處理,客戶端負責存儲
客戶端發送cookie:賬戶和密碼
服務端收到後確認登錄setCookie:sessionID=1,記下sessionID
客戶端收到sessionID後記錄,以後請求服務端帶上對比記錄下sessionID,說明已經登錄
會話管理:登錄狀態,購物車
個性化:用戶偏好,主題
Tracking:分析用戶行為
XXS:跨腳本攻擊,及使用javaScript拿到瀏覽器的cookie之後,發送到自己的網站,以這種方式來盜用用戶Cookie。Server在發送Cookie時,敏感的Cookie加上HttpOnly,這樣Cookie只能用於http請求,不能被JavaScript調用
XSRF:跨站請求偽造。Referer 從哪個網站跳轉過來
兩種方式:Basic和Bearer
首先第三方網站向授權網站申請第三方授權合作,拿到授權方頒發的client_id和client_secret(一般都是appid+appkey的方式)。
在這就過程中申請的client_secret是伺服器持有的,安全起見不能給客戶端,用服務端去和授權方獲取用戶信息,再傳給客戶端,包括④,⑤的請求過程也是需要加密的。這才是標準的授權過程。
有了access_token之後,就可以向授權方發送請求來獲取用戶信息
步驟分析就是上面的內容,這里把第4,6,8請求的參數分析一下
第④步參數:
response_type:指授權類型,必選,這里填固定值『code』
client_id:指客戶端id,必選,這里填在平台報備時獲取的appid
redirect_uri:指重定向URI,可選
scope:指申請的許可權范圍,可選
state:指客戶端當前狀態,可選,若填了,則認證伺服器會原樣返回該值
第⑥步參數:
grant_type:指使用哪種授權模式,必選,這里填固定值『authorization_code』
code:指從第⑤步獲取的code,必選
redirect_uri:指重定向URI,必選,這個值需要和第④步中的redirect_uri保持一致
client_id:指客戶端id,必選,這里填在平台報備時獲取的appid
client_secret:指客戶端密鑰,必選,這里填在平台報備時獲取的appkey
第⑧步參數:
access_token:指訪問令牌,必選,這里填第⑦步獲取的access_token
token_type:指令牌類型,必選,大小寫不敏感,bearer類型 / mac類型
expires_in:指過期時間,單位秒,當其他地方已設置過期時間,此處可省略該參數
refresh_token:指更新令牌,可選,用即將過期token換取新token
scope:指許可權范圍,可選,第④步中若已申請過某許可權,此處可省略該參數
我們在上面的第八步中會有refresh_token的參數,這個在實際操作中也比較常見
有時候我們在自己的項目中,將登陸和授權設計成類似OAuth2的過程,不過去掉Authorization code。登陸成功返回access_token,然後客戶端再請求時,帶上access_token。
我們常常會說到TCP/IP,那到底是什麼呢。這就需要講到網路分層模型。TCP在傳輸層,IP在網路層。那為什麼需要分層?因為網路不穩定,導致需要重傳的問題。為了提高傳輸效率我們就需要分塊,在傳輸層中就會進行分塊。TCP還有兩個重要的內容就是三次握手,四次分手。
HTTPS 協議是由 HTTP 加上TLS/SSL協議構建的可進行加密傳輸、身份認證的網路協議,主要通過數字證書、加密演算法、非對稱密鑰等技術完成互聯網數據傳輸加密,實現互聯網傳輸安全保護
1.客戶端通過發送Client Hello報文開始SSL通信。報文中包含客戶端支持的SSL的指定版本、加密組件列表(所使用的加密演算法及密鑰長度),客戶端隨機數,hash演算法。
2.伺服器可進行SSL通信時,會以Server Hello報文作為應答。和客戶端一樣,在報文中包含SSL版本以及加密組件,服務端隨機數。伺服器的加密組件內容是從接收到客戶端加密組件內篩選出來的。
3.之後伺服器發送Certificate報文。報文中包含公開密鑰證書。一般實際有三層證書嵌套,其實像下面圖二直接用根證書機構簽名也是可以的,但是一般根證書機構比較忙,需要類似中介的證書機構來幫助。
4.最後伺服器發送Server Hello Done報文通知客戶端,最初階段的SSL握手協商部分結束。
5.SSL第一次握手結束後,客戶端以Client Key Exchange報文作為回應。報文中包含通信加密中使用的一種被稱為Pre-master secret的隨機密碼串。該報文已用步驟3中的公開密鑰進行加密。
6.接著客戶端繼續發送Change Cipher Spec報文。該報文會提示伺服器,在此報文之後的通信會採用Pre-master secret密鑰加密。
7.客戶端發送Finished報文。該報文包含連接至今全部報文的整體校驗值。這次握手協商是否能夠成功,要以伺服器是否能夠正確解密報文作為判定標准。
8.伺服器同樣發送Change Cipher Spec報文。
9.伺服器同樣發送Finished報文。
10.伺服器和客戶端的Finished報文交換完畢之後,SSL連接就算建立完成。當然,通信會受到SSL的保護。從此處開始進行應用層協議的通信,即發送HTTP響應。
11.應用層協議通信,即發送HTTP響應。
12.最後由客戶端斷開連接。斷開連接時,發送close_notify報文。這步之後再發送TCP FIN報文來關閉與TCP的通信。
利用客戶端隨機數,服務端隨機數,per-master secret隨機數生成master secret,再生成客戶端加密密鑰,服務端加密密鑰,客戶端MAC secert,服務端MAC secert。MAC secert用於做報文摘要,這樣能夠查知報文是否遭到篡改,從而保護報文的完整性。
Android網路請求知識(一)HTTP基礎概念
Android網路請求知識(二)對稱和非對稱加密、數字簽名,Hash,Base64編碼
Android網路請求知識(三)授權,TCP/IP,HTTPS建立過程
Ⅳ Android上實現TCP服務端
之前已經講過了tcp客戶端的實現了,大家有興趣的話,可以參看文章
Android上實現TCP客戶端
那麼,今天我們就來講講tcp之服務端的封裝吧。我已經將tcp服務端封裝成了一個類—TcpServer,下面就來講講它的使用吧。
今天涉及內容:
先來波效果圖
在 tcp服務端 建立 ServerSocket 的時候,我們通常是這樣的:
其實以上方法調用的是
其中涉及到的參數:
鑒於tcp服務端 ServerSocket 一般運行在 "本機" 上,則快速初始化 ServerSocket 運用上面的方法:
意思是建立的ServerSocket IP地址為本機,可容納socket個數為 50 。
在理解了 ServerSocket 初始化問題後,讓我們來看看封裝類TcpServer的幾個主要方法:
TcpServer 主要是在 java 上運行,所以就讓我們在 Androidstudio 上模擬下在 Java 中運行tcp服務端的場景:
這里涉及到的兩個類 SocketConfig 和 SocketHelper 和之前的一樣,大家可以參考文章 Android上實現TCP客戶端 中與之相關的介紹,這里就不贅述了。
tcp服務端主要容易出現以下兩個問題:
對於第一個問題,這里需要強調的是 TcpServer 的接收方法 receiveMessage(String charsetName) 是以 (result = bufferedReader.readLine()) != null 做判斷讀取 stream 的,所以客戶端向 TcpServer 發送消息時,需要在結尾加上\n,這樣 TcpServer 的receiveMessage(String charsetName)方法才能將傳過來的數據接收完整。
對於第二個問題,則需要客戶端與服務端設置相同的字元集以保證數據不亂碼。
封裝類 TcpServer 源碼如下:
Ⅳ android socket用TCP方式client端怎麼監聽伺服器發送來的數據
伺服器端就是需要一個循環不停的接收,這樣才能保證伺服器能一直監聽客戶端傳過來的數據 你這是同步的,如果用非同步socket的話,BeginReceive裡面注冊了一個回調函數,在回調裡面再次調用BeginReceive就可以一直監聽了
Ⅵ Android中TCP客戶端怎麼可以及時判斷與服務端的異常斷開呀 我想在客戶
直接用BufferedReader
如果readLine() 返回為null的話, 表示socket已經斷開連接了, 因為readLine() 是阻塞的, 就是等伺服器的數據輸出, 一直等到返回了回車換行, 才會繼續執行。
Ⅶ android開發tcp客戶端循環接收信息,為什麼收不到呀
InputStream reader = socket.getInputStream()
byte[] bbuf = new byte[1000];
int count = reader.read(bbuf);
把讀取數據的方式改成這種試試,怕是你使用readline()方法的時候接收不到最後的「回車換行符」導致的。
Ⅷ 安卓串口轉tcp
安卓串口轉tcp是將設備串口數據傳到網路伺服器中,除了用DTU之外,還可以使用「MX虛擬串口」工具軟體,安裝在電腦或控制器中,簡單兩步配置即可實現。
1、下載安裝「MX虛擬串口」到官網下載www.meixuannet.cn。
2、創建「串口TCP客戶端」,實現串口轉tcp網路,寫入串口的數據會發給遠程tcp伺服器,方便實現遠程串口應用。
Ⅸ Android的APP客戶端和伺服器端一般是用什麼協議
HTTP 協議,建立在TCP/IP 的基礎上
FTP 協議
TCP/IP 協議,socket 編程(分客戶端和服務端)
Ⅹ android 客戶端用wifi socket Tcp/ip 連接上pc伺服器後一段時間後wifi關閉再打開,為什麼伺服器就收不到客
沒設置