真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

android通信協(xié)議,Android通信

Android通信方式篇(七)-Binder機(jī)制(Native層(下))

本篇文章針對向ServiceManager注冊服務(wù) 和 獲取服務(wù)兩個流程來做總結(jié)。在這兩個過程中,ServiceManager都扮演的是服務(wù)端,與客戶端之間的通信也是通過Binder IPC。

德興網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián)公司,德興網(wǎng)站設(shè)計制作,有大型網(wǎng)站制作公司豐富經(jīng)驗。已為德興近1000家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)網(wǎng)站制作要多少錢,請找那個售后服務(wù)好的德興做網(wǎng)站的公司定做!

在此之前先了解下Binder的進(jìn)程與線程的關(guān)系:

用戶空間 :ProcessState描述一個進(jìn)程,IPCThreadState對應(yīng)一個進(jìn)程中的一個線程。

內(nèi)核空間 :binder_proc描述一個進(jìn)程,統(tǒng)一由binder_procs全局鏈表保存,binder_thread對應(yīng)進(jìn)程的一個線程。

ProcessState與binder_proc是一一對應(yīng)的。

Binder線程池 :每個Server進(jìn)程在啟動時會創(chuàng)建一個binder線程池,并向其中注冊一個Binder線程;之后Server進(jìn)程也可以向binder線程池注冊新的線程,或者Binder驅(qū)動在探測到?jīng)]有空閑binder線程時會主動向Server進(jìn)程注冊新的的binder線程。對于一個Server進(jìn)程有一個最大Binder線程數(shù)限制15,(#define DEFAULT_MAX_BINDER_THREADS 15)。對于所有Client端進(jìn)程的binder請求都是交由Server端進(jìn)程的binder線程來處理的。我的理解是:binder線程是進(jìn)程進(jìn)行binder ipc時的一條數(shù)據(jù)處理路徑。

MediaPlayerService向ServiceManager注冊過程如下:

相關(guān)類:

整個過程總結(jié)如下:

1 獲取BpServiceManager 與 BpBinder

由defaultServiceManager()返回的是BpServiceManager,同時會創(chuàng)建ProcessState對象和BpBinder對象。然后通過BpBinder執(zhí)行transact,把真正工作交給IPCThreadState來處理。

2 BpBinder transact

Binder代理類調(diào)用transact()方法,真正工作還是交給IPCThreadState來進(jìn)行transact工作。

3 通過IPCThreadState 包裝并轉(zhuǎn)換數(shù)據(jù)并進(jìn)行transact事務(wù)處理

每個線程都有一個IPCThreadState,每個IPCThreadState中都有一對Parcel變量:mIn、mOut。相當(dāng)于兩根數(shù)據(jù)管道:

最后執(zhí)行talkWithDriver。

writeTransactionData:將BC Protocol + binder_transaction_data結(jié)構(gòu)體 寫入mOut, 然后執(zhí)行waitForResponse:

由talkWithDriver將數(shù)據(jù)進(jìn)一步封裝到binder_write_read結(jié)構(gòu)體,通過ioctl(BINDER_WRITE_READ)與驅(qū)動通信。同時等待驅(qū)動返回的接收BR命令,從mIn取出返回的數(shù)據(jù)。

mIn包裝的數(shù)據(jù)結(jié)構(gòu)(注冊服務(wù)handle = 0 ,code 為ADD_SERVICE_TRANSACTION):

4 Binder Driver

把binder_write_read結(jié)構(gòu)體write_buffer里數(shù)據(jù)取出來,分別得到BC命令和封裝好數(shù)據(jù)的事務(wù)binder_transaction_data, 然后根據(jù)handler,在當(dāng)前binder_proc中,找到相應(yīng)的binder_ref,由binder_ref再找到目標(biāo)binder_node實體,由目標(biāo)binder_node再找到目標(biāo)進(jìn)程binder_proc。然后就是插入數(shù)據(jù):當(dāng)binder驅(qū)動可以找到合適的線程,就會把binder_transaction節(jié)點插入到servciemanager的線程的todo隊列中,如果找不到合適的線程,就把節(jié)點之間插入servciemanager的binder_proc的todo隊列。

5 ServiceManager

經(jīng)過Binder Driver的處理,數(shù)據(jù)已經(jīng)到了ServiceManager進(jìn)程,在BR_TRANSACTION的引導(dǎo)下,在binder_loop()中執(zhí)行binder_parser()取出數(shù)據(jù),執(zhí)行do_add_service()操作,最終向 svcinfo 列表中添加已經(jīng)注冊的服務(wù)(沒有數(shù)據(jù)的返回)。最后發(fā)送 BR_REPLY 命令喚醒等待的線程,通知注冊成功。結(jié)束MediaPlayerService進(jìn)程 waitForResponse()的狀態(tài),整個注冊過程結(jié)束。

獲取服務(wù)的過程與注冊類似,首先 ServiceManager 向 Binder 驅(qū)動發(fā)送 BC_TRANSACTION 命令攜帶 CHECK_SERVICE_TRANSACTION 命令,同時獲取服務(wù)的線程進(jìn)入等待狀態(tài) waitForResponse()。Binder 驅(qū)動收到請求命令向 ServiceManager 的發(fā)送 BC_TRANSACTION 查詢已注冊的服務(wù),會區(qū)分請求服務(wù)所屬進(jìn)程情況。

查詢到直接響應(yīng) BR_REPLY 喚醒等待的線程。若查詢不到將與 binder_procs 鏈表中的服務(wù)進(jìn)行一次通訊再響應(yīng)。

以startService為例來簡單總結(jié)下執(zhí)行流程:

3.1 從方法執(zhí)行流程來看:

Client :

1 AMP.startService 標(biāo)記方法以及通過Parcel包裝數(shù)據(jù);

2 BinderProxy.transact 實際調(diào)用native的 android_os_BinderProxy_transact 傳遞數(shù)據(jù);

3 獲取BpServiceManager 與 BpBinder 同時會創(chuàng)建ProcessState。然后通過BpBinder執(zhí)行transact,把真正工作交給IPCThreadState來處理;

4 IPC.transact 主要執(zhí)行writeTransactionData,將上層傳來的數(shù)據(jù)重新包裝成binder_transaction_data,并將BC Protocol + binder_transaction_data結(jié)構(gòu)體 寫入mOut;

5 IPC waitForResponse talkWithDriver + 等待返回數(shù)據(jù);

6 talkWithDriver 將數(shù)據(jù)進(jìn)一步封裝成binder_write_read,通過ioctl(BINDER_WRITE_READ)與驅(qū)動通信;

Kernel :

7 binder ioctl 接收BINDER_WRITE_READ ioctl命令;

8 binder_ioctl_write_read 把用戶空間數(shù)據(jù)ubuf拷貝到內(nèi)核空間bwr;

9 binder_thread_write 當(dāng)bwr寫緩存有數(shù)據(jù),則執(zhí)行binder_thread_write;當(dāng)寫失敗則將bwr數(shù)據(jù)寫回用戶空間并退出;

10 binder_transaction 找到目標(biāo)進(jìn)程binder_proc并插入數(shù)據(jù)到目標(biāo)進(jìn)程的線程todo隊列,最終執(zhí)行到它

時,將發(fā)起端數(shù)據(jù)拷貝到接收端進(jìn)程的buffer結(jié)構(gòu)體;

11 binder_thread_read 根據(jù)binder_transaction結(jié)構(gòu)體和binder_buffer結(jié)構(gòu)體數(shù)據(jù)生成新的binder_transaction_data結(jié)構(gòu)體,寫入bwr的read_buffer,當(dāng)bwr讀緩存有數(shù)據(jù),則執(zhí)行binder_thread_read;當(dāng)讀失敗則再將bwr數(shù)據(jù)寫回用戶空間并退出;最后,把內(nèi)核數(shù)據(jù)bwr拷貝到用戶空間ubuf。

12 binder_thread_write + binder_ioctl BR命令和數(shù)據(jù)傳遞

Server:

13 IPC.executeCommand 解析kernel傳過來的binder_transaction_data數(shù)據(jù),找到目標(biāo)BBinder并調(diào)用其transact()方法;

14 IPC.joinThreadPool 采用循環(huán)不斷地執(zhí)行g(shù)etAndExecuteCommand()方法, 處理事務(wù)。當(dāng)bwr的讀寫buffer都沒有數(shù)據(jù)時,則阻塞在binder_thread_read的wait_event過程. 另外,正常情況下binder線程一旦創(chuàng)建則不會退出.

15 BBinder.transact 到Binder.exeTransact 調(diào)用 AMN.onTransact

16 AMN.onTransact 把數(shù)據(jù)傳遞到AMS.starService去執(zhí)行

17 AMS.starService Server處理了Client的請求了

然后原路replay回去,talkWithDriver 到Kernel ,然后找到Client進(jìn)程,把數(shù)據(jù)拷貝到read_buffer里,最終喚醒IPC,把反饋傳遞回AMP.startService。完成啟動服務(wù)。

3.2 從通信協(xié)議流程來看:

非oneWay:

oneway:

oneway與非oneway區(qū)別: 都是需要等待Binder Driver的回應(yīng)消息BR_TRANSACTION_COMPLETE. 主要區(qū)別在于oneway的通信收到BR_TRANSACTION_COMPLETE則返回,而不會再等待BR_REPLY消息的到來. 另外,oneway的binder IPC則接收端無法獲取對方的pid.

3.3 從數(shù)據(jù)流來看

從用戶空間開始:

進(jìn)入驅(qū)動后:

回到用戶空間:

參考:

Android網(wǎng)絡(luò)請求知識(三)授權(quán),TCP/IP,HTTPS建立過程

由身份或持有的令牌確認(rèn)享有的權(quán)限,登錄過程實質(zhì)上的目的也是為了確認(rèn)權(quán)限。

Cookie是客戶端給服務(wù)器用的,setCookie是服務(wù)器給客戶端用的。cookie由服務(wù)器處理,客戶端負(fù)責(zé)存儲

客戶端發(fā)送cookie:賬戶和密碼

服務(wù)端收到后確認(rèn)登錄setCookie:sessionID=1,記下sessionID

客戶端收到sessionID后記錄,以后請求服務(wù)端帶上對比記錄下sessionID,說明已經(jīng)登錄

會話管理:登錄狀態(tài),購物車

個性化:用戶偏好,主題

Tracking:分析用戶行為

XXS:跨腳本攻擊,及使用JavaScript拿到瀏覽器的cookie之后,發(fā)送到自己的網(wǎng)站,以這種方式來盜用用戶Cookie。Server在發(fā)送Cookie時,敏感的Cookie加上HttpOnly,這樣Cookie只能用于http請求,不能被JavaScript調(diào)用

XSRF:跨站請求偽造。Referer 從哪個網(wǎng)站跳轉(zhuǎn)過來

兩種方式:Basic和Bearer

首先第三方網(wǎng)站向授權(quán)網(wǎng)站申請第三方授權(quán)合作,拿到授權(quán)方頒發(fā)的client_id和client_secret(一般都是appid+appkey的方式)。

在這就過程中申請的client_secret是服務(wù)器持有的,安全起見不能給客戶端,用服務(wù)端去和授權(quán)方獲取用戶信息,再傳給客戶端,包括④,⑤的請求過程也是需要加密的。這才是標(biāo)準(zhǔn)的授權(quán)過程。

有了access_token之后,就可以向授權(quán)方發(fā)送請求來獲取用戶信息

步驟分析就是上面的內(nèi)容,這里把第4,6,8請求的參數(shù)分析一下

第④步參數(shù):

response_type:指授權(quán)類型,必選,這里填固定值‘code’

client_id:指客戶端id,必選,這里填在平臺報備時獲取的appid

redirect_uri:指重定向URI,可選

scope:指申請的權(quán)限范圍,可選

state:指客戶端當(dāng)前狀態(tài),可選,若填了,則認(rèn)證服務(wù)器會原樣返回該值

第⑥步參數(shù):

grant_type:指使用哪種授權(quán)模式,必選,這里填固定值‘a(chǎn)uthorization_code’

code:指從第⑤步獲取的code,必選

redirect_uri:指重定向URI,必選,這個值需要和第④步中的redirect_uri保持一致

client_id:指客戶端id,必選,這里填在平臺報備時獲取的appid

client_secret:指客戶端密鑰,必選,這里填在平臺報備時獲取的appkey

第⑧步參數(shù):

access_token:指訪問令牌,必選,這里填第⑦步獲取的access_token

token_type:指令牌類型,必選,大小寫不敏感,bearer類型 / mac類型

expires_in:指過期時間,單位秒,當(dāng)其他地方已設(shè)置過期時間,此處可省略該參數(shù)

refresh_token:指更新令牌,可選,用即將過期token換取新token

scope:指權(quán)限范圍,可選,第④步中若已申請過某權(quán)限,此處可省略該參數(shù)

我們在上面的第八步中會有refresh_token的參數(shù),這個在實際操作中也比較常見

有時候我們在自己的項目中,將登陸和授權(quán)設(shè)計成類似OAuth2的過程,不過去掉Authorization code。登陸成功返回access_token,然后客戶端再請求時,帶上access_token。

我們常常會說到TCP/IP,那到底是什么呢。這就需要講到網(wǎng)絡(luò)分層模型。TCP在傳輸層,IP在網(wǎng)絡(luò)層。那為什么需要分層?因為網(wǎng)絡(luò)不穩(wěn)定,導(dǎo)致需要重傳的問題。為了提高傳輸效率我們就需要分塊,在傳輸層中就會進(jìn)行分塊。TCP還有兩個重要的內(nèi)容就是三次握手,四次分手。

HTTPS 協(xié)議是由 HTTP 加上TLS/SSL協(xié)議構(gòu)建的可進(jìn)行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議,主要通過數(shù)字證書、加密算法、非對稱密鑰等技術(shù)完成互聯(lián)網(wǎng)數(shù)據(jù)傳輸加密,實現(xiàn)互聯(lián)網(wǎng)傳輸安全保護(hù)

1.客戶端通過發(fā)送Client Hello報文開始SSL通信。報文中包含客戶端支持的SSL的指定版本、加密組件列表(所使用的加密算法及密鑰長度),客戶端隨機(jī)數(shù),hash算法。

2.服務(wù)器可進(jìn)行SSL通信時,會以Server Hello報文作為應(yīng)答。和客戶端一樣,在報文中包含SSL版本以及加密組件,服務(wù)端隨機(jī)數(shù)。服務(wù)器的加密組件內(nèi)容是從接收到客戶端加密組件內(nèi)篩選出來的。

3.之后服務(wù)器發(fā)送Certificate報文。報文中包含公開密鑰證書。一般實際有三層證書嵌套,其實像下面圖二直接用根證書機(jī)構(gòu)簽名也是可以的,但是一般根證書機(jī)構(gòu)比較忙,需要類似中介的證書機(jī)構(gòu)來幫助。

4.最后服務(wù)器發(fā)送Server Hello Done報文通知客戶端,最初階段的SSL握手協(xié)商部分結(jié)束。

5.SSL第一次握手結(jié)束后,客戶端以Client Key Exchange報文作為回應(yīng)。報文中包含通信加密中使用的一種被稱為Pre-master secret的隨機(jī)密碼串。該報文已用步驟3中的公開密鑰進(jìn)行加密。

6.接著客戶端繼續(xù)發(fā)送Change Cipher Spec報文。該報文會提示服務(wù)器,在此報文之后的通信會采用Pre-master secret密鑰加密。

7.客戶端發(fā)送Finished報文。該報文包含連接至今全部報文的整體校驗值。這次握手協(xié)商是否能夠成功,要以服務(wù)器是否能夠正確解密報文作為判定標(biāo)準(zhǔn)。

8.服務(wù)器同樣發(fā)送Change Cipher Spec報文。

9.服務(wù)器同樣發(fā)送Finished報文。

10.服務(wù)器和客戶端的Finished報文交換完畢之后,SSL連接就算建立完成。當(dāng)然,通信會受到SSL的保護(hù)。從此處開始進(jìn)行應(yīng)用層協(xié)議的通信,即發(fā)送HTTP響應(yīng)。

11.應(yīng)用層協(xié)議通信,即發(fā)送HTTP響應(yīng)。

12.最后由客戶端斷開連接。斷開連接時,發(fā)送close_notify報文。這步之后再發(fā)送TCP FIN報文來關(guān)閉與TCP的通信。

利用客戶端隨機(jī)數(shù),服務(wù)端隨機(jī)數(shù),per-master secret隨機(jī)數(shù)生成master secret,再生成客戶端加密密鑰,服務(wù)端加密密鑰,客戶端MAC secert,服務(wù)端MAC secert。MAC secert用于做報文摘要,這樣能夠查知報文是否遭到篡改,從而保護(hù)報文的完整性。

Android網(wǎng)絡(luò)請求知識(一)HTTP基礎(chǔ)概念

Android網(wǎng)絡(luò)請求知識(二)對稱和非對稱加密、數(shù)字簽名,Hash,Base64編碼

Android網(wǎng)絡(luò)請求知識(三)授權(quán),TCP/IP,HTTPS建立過程

Android socket通信協(xié)議的封裝和解析

android socket通信協(xié)議的封裝和解析,其實是和java一樣的,都是通過http中的相關(guān)知識來封裝和解析,主要是通過多次握手,如下代碼:

import?java.io.BufferedReader;

import?java.io.BufferedWriter;

import?java.io.IOException;

import?java.io.InputStreamReader;

import?java.io.OutputStreamWriter;

import?java.io.PrintWriter;

import?java.net.ServerSocket;

import?java.net.Socket;

import?java.util.ArrayList;

import?java.util.List;

import?java.util.concurrent.ExecutorService;

import?java.util.concurrent.Executors;

public?class?Main?{

private?static?final?int?PORT?=?9999;

private?ListSocket?mList?=?new?ArrayListSocket();

private?ServerSocket?server?=?null;

private?ExecutorService?mExecutorService?=?null;?//thread?pool

public?static?void?main(String[]?args)?{

new?Main();

}

public?Main()?{

try?{

server?=?new?ServerSocket(PORT);

mExecutorService?=?Executors.newCachedThreadPool();??//create?a?thread?pool

System.out.println("服務(wù)器已啟動...");

Socket?client?=?null;

while(true)?{

client?=?server.accept();

//把客戶端放入客戶端集合中

mList.add(client);

mExecutorService.execute(new?Service(client));?//start?a?new?thread?to?handle?the?connection

}

}catch?(Exception?e)?{

e.printStackTrace();

}

}

class?Service?implements?Runnable?{

private?Socket?socket;

private?BufferedReader?in?=?null;

private?String?msg?=?"";

public?Service(Socket?socket)?{

this.socket?=?socket;

try?{

in?=?new?BufferedReader(new?InputStreamReader(socket.getInputStream()));

//客戶端只要一連到服務(wù)器,便向客戶端發(fā)送下面的信息。

msg?=?"服務(wù)器地址:"?+this.socket.getInetAddress()?+?"come?toal:"

+mList.size()+"(服務(wù)器發(fā)送)";

this.sendmsg();

}?catch?(IOException?e)?{

e.printStackTrace();

}

}

@Override

public?void?run()?{

try?{

while(true)?{

if((msg?=?in.readLine())!=?null)?{

//當(dāng)客戶端發(fā)送的信息為:exit時,關(guān)閉連接

if(msg.equals("exit"))?{

System.out.println("ssssssss");

mList.remove(socket);

in.close();

msg?=?"user:"?+?socket.getInetAddress()

+?"exit?total:"?+?mList.size();

socket.close();

this.sendmsg();

break;

//接收客戶端發(fā)過來的信息msg,然后發(fā)送給客戶端。

}?else?{

msg?=?socket.getInetAddress()?+?":"?+?msg+"(服務(wù)器發(fā)送)";

this.sendmsg();

}

}

}

}?catch?(Exception?e)?{

e.printStackTrace();

}

}

/**

*?循環(huán)遍歷客戶端集合,給每個客戶端都發(fā)送信息。

*/

public?void?sendmsg()?{

System.out.println(msg);

int?num?=mList.size();

for?(int?index?=?0;?index??num;?index?++)?{

Socket?mSocket?=?mList.get(index);

PrintWriter?pout?=?null;

try?{

pout?=?new?PrintWriter(new?BufferedWriter(

new?OutputStreamWriter(mSocket.getOutputStream())),true);

pout.println(msg);

}catch?(IOException?e)?{

e.printStackTrace();

}

}

}

}????

}


當(dāng)前文章:android通信協(xié)議,Android通信
標(biāo)題路徑:http://weahome.cn/article/dsdcjho.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部