国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android中socketpair雙向通信詳解

2019-10-22 18:29:32
字體:
來源:轉載
供稿:網友

Android很多地方會涉及到進程間的通信,比如輸入系統,那么進程間通信會涉及哪些內容呢?

1、進程:負責讀取和分發事件
2、應用程序:負責處理輸入事件

上面這兩個進程會涉及哪些雙向通信呢:

1.進程會發送輸入事件
2.應用程序會告知事件處理完或APP已關閉

這里大家可能會有疑惑,binder系統能否實現上面所說的雙向通信呢?

答案是不行,binder分為server和client,每次都由client主動發出請求,server收到請求后進行答復,這樣的缺點就是每次請求只能單方發起,server不能主動發送數據給client,這樣自然不能稱為雙向通信。

所以這里引入一個新的方法,叫“socketpair”

APP通過socketpair調用得到兩個文件句柄,假設這兩個文件句柄是fd1和fd2,這兩個文件都對應有兩個緩沖區(send_buf、rcv_buf),當某個進程或線程通過fd1寫到他的send_buf的時候,內核里面的socket就會把send_buf里面的數據寫到fd2的rcv_buf里面,另外一個線程或進程就可以讀取fd2得到那些數據了,相反同理。

但是它也有缺點:由于是通過創建文件句柄來訪問句柄實現的通信,那么誰可以看到這個句柄呢,只有當前APP創建出來的線程或它創建出來的子進程才能看到這些文件句柄,所以只適用于線程間通信,或者具有親緣關系(父子進程)的進程間通信。

那么如果想使用socketpair來實現任意間的進程間的雙向通信怎么辦?
假設現在有APP1和APP2,這兩個APP想進行任意間的進程通信,那么APP2需要得到APP1的fd2才行,怎么得到呢?可以通過binder通信,把fd2傳給APP2,當然在APP2里面它就變為fd3了,這樣這個任意的進程APP2就可以通過socketpair來進行通信了。這篇暫不講解binder的實現方式

下面講解一下“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函數實現 */ void *function_thread1 (void *arg) { int fd = (int)arg;/* 把文件句柄轉換出來 */ char buf[500]; int len; int cnt = 0; while (1) { /* 向 main線程發出: Hello, main thread */ len = sprintf(buf, "Hello, main thread, cnt = %d", cnt++); write(fd, buf, len); /* 讀取數據(main線程發回的數據) */ 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 得到兩個文件句柄到數組sockets */ socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets); /* 設置緩沖區, 每個文件句柄對應兩個緩沖區,兩個文件對應四個 */ 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)); /* 創建線程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];/* 當前main函數的文件句柄是sockets[0] */ while(1) { /* 讀數據: 讀線程1發出的數據 */ len = read(fd, buf, 500); buf[len] = '/0'; printf("%s/n", buf); /* main thread向thread1 發出: Hello, thread1 */ len = sprintf(buf, "Hello, thread1, cnt = %d", cnt++); write(fd, buf, len); } }

程序非常簡單,先是使用socketpair得到兩個文件句柄并設置發送接收緩沖區,然后創建另一個線程,在線程中通過文件句柄讀寫數據到main線程中,mian也執行同樣的操作實現雙向通信。

測試驗證:

socketpair,雙向通信

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

socketpair,雙向通信

我們還可以修改程序,讓應用程序fork出一個子進程,然后讓父子進程通過socketpair來實現雙向通信,比較簡單,這里就不細講了。

由于socekpair只適用于線程間通信,或者具有親緣關系,如果想實現任意的兩個進程間的雙向通信就需要使用binder系統把fd傳給另一個進程,這里簡單說下過程,如下:

使用binder傳輸文件句柄:

  • 假設APP1,open某個文件句柄得到fd1
  • 通過binder驅動根據fd1得到file結構體,即files->fdt->fd[fd1]
  • 從APP2的files->fdt->fd中取出一個空項,假設是fd2,讓fd2指向fd1的file結構體,即files->fdt->fd[fd2]=file
  • 之后APP1可以通過fd1,APP2可以通過fd2訪問同一個文件了

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 鹤峰县| 平江县| 茶陵县| 哈尔滨市| 化州市| 宿州市| 香河县| 南溪县| 阿勒泰市| 福海县| 遂川县| 高尔夫| 海兴县| 怀远县| 沙湾县| 娄底市| 泗水县| 德州市| 称多县| 绥德县| 衡东县| 同心县| 资溪县| 兴海县| 长春市| 金川县| 马公市| 喀什市| 沧州市| 泽普县| 马尔康县| 揭阳市| 中卫市| 弥勒县| 双峰县| 甘泉县| 车险| 曲麻莱县| 凉山| 永川市| 古浪县|