Android中socketpair雙向通信詳解
Android很多地方會涉及到進(jìn)程間的通信,比如輸入系統(tǒng),那么進(jìn)程間通信會涉及哪些內(nèi)容呢?
1、進(jìn)程:負(fù)責(zé)讀取和分發(fā)事件
2、應(yīng)用程序:負(fù)責(zé)處理輸入事件
上面這兩個進(jìn)程會涉及哪些雙向通信呢:
1.進(jìn)程會發(fā)送輸入事件
2.應(yīng)用程序會告知事件處理完或APP已關(guān)閉
這里大家可能會有疑惑,binder系統(tǒng)能否實(shí)現(xiàn)上面所說的雙向通信呢?
答案是不行,binder分為server和client,每次都由client主動發(fā)出請求,server收到請求后進(jìn)行答復(fù),這樣的缺點(diǎn)就是每次請求只能單方發(fā)起,server不能主動發(fā)送數(shù)據(jù)給client,這樣自然不能稱為雙向通信。
所以這里引入一個新的方法,叫“socketpair”
APP通過socketpair調(diào)用得到兩個文件句柄,假設(shè)這兩個文件句柄是fd1和fd2,這兩個文件都對應(yīng)有兩個緩沖區(qū)(send_buf、rcv_buf),當(dāng)某個進(jìn)程或線程通過fd1寫到他的send_buf的時候,內(nèi)核里面的socket就會把send_buf里面的數(shù)據(jù)寫到fd2的rcv_buf里面,另外一個線程或進(jìn)程就可以讀取fd2得到那些數(shù)據(jù)了,相反同理。
但是它也有缺點(diǎn):由于是通過創(chuàng)建文件句柄來訪問句柄實(shí)現(xiàn)的通信,那么誰可以看到這個句柄呢,只有當(dāng)前APP創(chuàng)建出來的線程或它創(chuàng)建出來的子進(jìn)程才能看到這些文件句柄,所以只適用于線程間通信,或者具有親緣關(guān)系(父子進(jìn)程)的進(jìn)程間通信。
那么如果想使用socketpair來實(shí)現(xiàn)任意間的進(jìn)程間的雙向通信怎么辦?
假設(shè)現(xiàn)在有APP1和APP2,這兩個APP想進(jìn)行任意間的進(jìn)程通信,那么APP2需要得到APP1的fd2才行,怎么得到呢?可以通過binder通信,把fd2傳給APP2,當(dāng)然在APP2里面它就變?yōu)閒d3了,這樣這個任意的進(jìn)程APP2就可以通過socketpair來進(jìn)行通信了。這篇暫不講解binder的實(shí)現(xiàn)方式
下面講解一下“Socketpair”的程序及使用:
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#define SOCKET_BUFFER_SIZE (32768U)
/* 參考:
* frameworks\native\libs\input\InputTransport.cpp
*/
/* 線程1函數(shù)實(shí)現(xiàn) */
void *function_thread1 (void *arg)
{
int fd = (int)arg;/* 把文件句柄轉(zhuǎn)換出來 */
char buf[500];
int len;
int cnt = 0;
while (1)
{
/* 向 main線程發(fā)出: Hello, main thread */
len = sprintf(buf, "Hello, main thread, cnt = %d", cnt++);
write(fd, buf, len);
/* 讀取數(shù)據(jù)(main線程發(fā)回的數(shù)據(jù)) */
len = read(fd, buf, 500);
buf[len] = '\0';
printf("%s\n", buf);
/* 延時5秒鐘 */
sleep(5);
}
return NULL;
}
int main(int argc, char **argv)
{
int sockets[2];
/* 使用 socketpair 得到兩個文件句柄到數(shù)組sockets */
socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets);
/* 設(shè)置緩沖區(qū), 每個文件句柄對應(yīng)兩個緩沖區(qū),兩個文件對應(yīng)四個 */
int bufferSize = SOCKET_BUFFER_SIZE;
setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
/* 創(chuàng)建線程1(thread1),并把文件句柄sockets[1]傳給子線程thread1 */
pthread_t threadID;
pthread_create(&threadID, NULL, function_thread1, (void *)sockets[1]);
char buf[500];
int len;
int cnt = 0;
int fd = sockets[0];/* 當(dāng)前main函數(shù)的文件句柄是sockets[0] */
while(1)
{
/* 讀數(shù)據(jù): 讀線程1發(fā)出的數(shù)據(jù) */
len = read(fd, buf, 500);
buf[len] = '\0';
printf("%s\n", buf);
/* main thread向thread1 發(fā)出: Hello, thread1 */
len = sprintf(buf, "Hello, thread1, cnt = %d", cnt++);
write(fd, buf, len);
}
}
程序非常簡單,先是使用socketpair得到兩個文件句柄并設(shè)置發(fā)送接收緩沖區(qū),然后創(chuàng)建另一個線程,在線程中通過文件句柄讀寫數(shù)據(jù)到main線程中,mian也執(zhí)行同樣的操作實(shí)現(xiàn)雙向通信。
測試驗(yàn)證:

檢查是否存在這兩個線程:

我們還可以修改程序,讓應(yīng)用程序fork出一個子進(jìn)程,然后讓父子進(jìn)程通過socketpair來實(shí)現(xiàn)雙向通信,比較簡單,這里就不細(xì)講了。
由于socekpair只適用于線程間通信,或者具有親緣關(guān)系,如果想實(shí)現(xiàn)任意的兩個進(jìn)程間的雙向通信就需要使用binder系統(tǒng)把fd傳給另一個進(jìn)程,這里簡單說下過程,如下:
使用binder傳輸文件句柄:
- 假設(shè)APP1,open某個文件句柄得到fd1
- 通過binder驅(qū)動根據(jù)fd1得到file結(jié)構(gòu)體,即files->fdt->fd[fd1]
- 從APP2的files->fdt->fd中取出一個空項(xiàng),假設(shè)是fd2,讓fd2指向fd1的file結(jié)構(gòu)體,即files->fdt->fd[fd2]=file
- 之后APP1可以通過fd1,APP2可以通過fd2訪問同一個文件了
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android 分析實(shí)現(xiàn)性能優(yōu)化之啟動速度優(yōu)化
在移動端程序中,用戶希望的是應(yīng)用能夠快速打開。啟動時間過長的應(yīng)用不能滿足這個期望,并且可能會令用戶失望。輕則鄙視你,重則直接卸載你的應(yīng)用2021-11-11
Android?Springboot?實(shí)現(xiàn)SSE通信案例詳解
SSE是一種用于實(shí)現(xiàn)服務(wù)器主動向客戶端推送數(shù)據(jù)的技術(shù),它基于?HTTP?協(xié)議,利用了其長連接特性,在客戶端與服務(wù)器之間建立一條持久化連接,并通過這條連接實(shí)現(xiàn)服務(wù)器向客戶端的實(shí)時數(shù)據(jù)推送,這篇文章主要介紹了Android?Springboot?實(shí)現(xiàn)SSE通信案例,需要的朋友可以參考下2024-07-07
Android自定義控件之繼承ViewGroup創(chuàng)建新容器
這篇文章主要介紹了Android自定義控件之繼承ViewGroup創(chuàng)建新容器,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-12-12
Android提高之模擬信號示波器的實(shí)現(xiàn)
這篇文章主要介紹了Android模擬信號示波器的實(shí)現(xiàn)方法,在Android項(xiàng)目開發(fā)中有一定的實(shí)用價值,需要的朋友可以參考下2014-08-08
基于Android中dp和px之間進(jìn)行轉(zhuǎn)換的實(shí)現(xiàn)代碼
本篇文章是對在Android中dp和px之間進(jìn)行轉(zhuǎn)換的實(shí)現(xiàn)方法進(jìn)行了分析介紹,需要的朋友參考下2013-05-05
通過實(shí)例簡單講解Android App中的Activity組件
這篇文章主要介紹了通過Android App中的Activity組件,包括Activity的定義和繼承以及啟動等基本知識,需要的朋友可以參考下2016-04-04
Android系統(tǒng)的五種數(shù)據(jù)存儲形式實(shí)例(一)
Android系統(tǒng)有五種數(shù)據(jù)存儲形式,分別是文件存儲、SP存儲、數(shù)據(jù)庫存儲、contentprovider 內(nèi)容提供者、網(wǎng)絡(luò)存儲。本篇文章詳解的介紹了每種數(shù)據(jù)存儲的用法,有興趣的可以了解一下。2016-12-12
android實(shí)現(xiàn)QQ微信側(cè)滑刪除效果
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)QQ微信側(cè)滑刪除效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-12-12

