亚欧色一区w666天堂,色情一区二区三区免费看,少妇特黄A片一区二区三区,亚洲人成网站999久久久综合,国产av熟女一区二区三区

  • 發布文章
  • 消息中心
點贊
收藏
評論
分享
原創

Android 進程間大數據通信: LocalSocket

2023-10-13 10:02:40
31
0

說起 Android 進行間通信,大家第一時間會想到 AIDL,但是由于 Binder 機制的限制,AIDL 無法傳輸超大數據。

 

那么我們如何在進程間傳輸大數據呢?

 

Android 中給我們提供了另外一個機制: LocalSocket。它會在本地創建一個 socket 通道來進行數據傳輸。

 

那么它怎么使用?

 

首先我們需要兩個應用: 客戶端和服務端。

 

服務端初始化
override fun run() {    
     server = LocalServerSocket("xxxx") 
     remoteSocket = server?.accept()
    ...
}

先創建一個 LocalServerSocket 服務,參數是服務名,注意這個服務名需要唯一,這是兩端連接的依據。

 

然后調用 accept 函數進行等待客戶端連接,這個函數是 block 線程的,所以例子中另起線程。

 

當客戶端發起連接后,accept 就會返回 LocalSocket 對象,然后就可以進行傳輸數據了。

客戶端初始化
var localSocket = LocalSocket()
localSocket.connect(LocalSocketAddress("xxxx"))
首先創建一個 LocalSocket 對象。
然后創建一個 LocalSocketAddress 對象,參數是服務名。
然后調用 connect 函數連接到該服務即可。就可以使用這個 socket 傳輸數據了。

 

數據傳輸

兩端的 socket 對象是一個類,所以兩端的發送和接受代碼邏輯一致。

 

通過 localSocket.inputStreamlocalSocket.outputStream 可以獲取到輸入輸出流,通過對流的讀寫進行數據傳輸。

 

注意,讀寫流的時候一定要新開線程處理。

 

因為 socket 是雙向的,所以兩端都可以進行收發,即讀寫。

發送數據

var pool = Executors.newSingleThreadExecutor()
var runnable = Runnable {
     try {
         var out = xxxxSocket.outputStream 
         out.write(data) out.flush() 
     } catch (e: Throwable) {
         Log.e("xxx", "xxx", e)
    }
}
pool.execute(runnable)
發送數據是主動動作,每次發送都需要另開線程,所以如果是多次,我們需要使用一個線程池來進行管理。
如果需要多次發送數據,可以將其進行封裝成一個函數。

 

接收數據
接收數據實際上是進行 while 循環,循環進行讀取數據,這個最好在連接成功后就開始,比如客戶端:
localSocket.connect(LocalSocketAddress("xxx"))
var runnable = Runnable { 
   while (localSocket.isConnected) {
         var input = localSocket.inputStreaminput.read(data)        
         ...
    }
}
Thread(runnable).start()
接收數據實際上是一個 while 循環不停的進行讀取,未讀到數據就繼續循環,讀到數據就進行處理再循環,所以這里只另開一個線程即可,不需要線程池。
傳輸復雜數據
上面只是簡單事例,無法傳輸復雜數據,如果要傳輸復雜數據,就需要使用 DataInputStreamDataOutputStream

首先需要定義一套協議。

 

比如定義一個簡單的協議: 傳輸的數據分兩部分,第一部分是一個 int 值,表示后面 byte 數據的長度;第二部分就是 byte 數據。這樣就知道如何進行讀寫。

 

寫數據

 
var pool = Executors.newSingleThreadExecutor()
var out = DataOutputStream(xxxSocket.outputStream)
var runnable = Runnable {
        try {
               out.writeInt(data.size) out.write(data) out.flush()
        } catch (e: Throwable) {
               Log.e("xxx", "xxx", e) 
        }
}
pool.execute(runnable)
 

 

讀數據

var runnable = Runnable { 
         var input = DataInputStream(xxxSocket.inputStream) 
         var outArray = ByteArrayOutputStream()
         while (true) {   
                 outArray.reset()
                 var length = input.readInt()
                 if(length > 0) {
                    var buffer = ByteArray(length)
                    input.read(buffer) 
                    ... 
                 }
        }
}
Thread(runnable).start()
這樣就可以傳輸復雜數據,不會導致數據錯亂。

 

傳輸超大數據
上面雖然可以傳輸復雜數據,但是當我們的數據過大的時候,也會出現問題。
比如傳輸圖片或視頻,假設 byte 數據長度達到 1228800,這時我們通過:
var buffer = ByteArray(1228800)
input.read(buffer)
無法讀取到所有數據,只能讀到一部分。而且會造成后面數據的混亂,因為讀取位置錯位了。
讀取的長度大約是 65535 個字節,這是因為 TCP 被 IP 包包著,也會有包大小限制 65535。
但是注意!寫數據的時候如果數據過大就會自動進行分包,但是讀數據的時候如果一次讀取貌似無法跨包,這樣就導致了上面的結果,只能讀一個包,后面的就錯亂了。
那么這種超大數據該如何傳輸呢,我們用循環將其一點點寫入,也一點點讀出,并根據結果不斷的修正偏移。代碼:

 

寫入

var pool = Executors.newSingleThreadExecutor()
var out = DataOutputStream(xxxSocket.outputStream)
var runnable = Runnable {
          try {
              out.writeInt(data.size) 
              var offset = 0 
              while ((offset + 1024) <= data.size) {
                  out.write(data, offset, 1024) 
                  offset += 1024 
              }
              out.write(data, offset, data.size - offset)
              out.flush()
           } catch (e: Throwable) {
              Log.e("xxxx", "xxxx", e)
           }
}
pool.execute(runnable)

 

讀取

var input = DataInputStream(xxxSocket.inputStream)
var runnable = Runnable {
          var outArray = ByteArrayOutputStream()
          while (true) {
                outArray.reset()
                var length = input.readInt()
                if(length > 0) {
                    var buffer = ByteArray(1024)
                    var total = 0 
                    while (total + 1024 <= length) {
                        var count = input.read(buffer)
                        outArray.write(buffer, 0, count)
                        total += count
                    }
                    var buffer2 = ByteArray(length - total)
                    input.read(buffer2)
                    outArray.write(buffer2)
                    var result = outArray.toByteArray()
                    ... 
                }
         }
}
Thread(runnable).start()
 
這樣可以避免因為分包而導致讀取的長度不匹配的問題。
0條評論
0 / 1000
wbq
18文章數
0粉絲數
wbq
18 文章 | 0 粉絲
wbq
18文章數
0粉絲數
wbq
18 文章 | 0 粉絲
原創

Android 進程間大數據通信: LocalSocket

2023-10-13 10:02:40
31
0

說起 Android 進行間通信,大家第一時間會想到 AIDL,但是由于 Binder 機制的限制,AIDL 無法傳輸超大數據。

 

那么我們如何在進程間傳輸大數據呢?

 

Android 中給我們提供了另外一個機制: LocalSocket。它會在本地創建一個 socket 通道來進行數據傳輸。

 

那么它怎么使用?

 

首先我們需要兩個應用: 客戶端和服務端。

 

服務端初始化
override fun run() {    
     server = LocalServerSocket("xxxx") 
     remoteSocket = server?.accept()
    ...
}

先創建一個 LocalServerSocket 服務,參數是服務名,注意這個服務名需要唯一,這是兩端連接的依據。

 

然后調用 accept 函數進行等待客戶端連接,這個函數是 block 線程的,所以例子中另起線程。

 

當客戶端發起連接后,accept 就會返回 LocalSocket 對象,然后就可以進行傳輸數據了。

客戶端初始化
var localSocket = LocalSocket()
localSocket.connect(LocalSocketAddress("xxxx"))
首先創建一個 LocalSocket 對象。
然后創建一個 LocalSocketAddress 對象,參數是服務名。
然后調用 connect 函數連接到該服務即可。就可以使用這個 socket 傳輸數據了。

 

數據傳輸

兩端的 socket 對象是一個類,所以兩端的發送和接受代碼邏輯一致。

 

通過 localSocket.inputStreamlocalSocket.outputStream 可以獲取到輸入輸出流,通過對流的讀寫進行數據傳輸。

 

注意,讀寫流的時候一定要新開線程處理。

 

因為 socket 是雙向的,所以兩端都可以進行收發,即讀寫。

發送數據

var pool = Executors.newSingleThreadExecutor()
var runnable = Runnable {
     try {
         var out = xxxxSocket.outputStream 
         out.write(data) out.flush() 
     } catch (e: Throwable) {
         Log.e("xxx", "xxx", e)
    }
}
pool.execute(runnable)
發送數據是主動動作,每次發送都需要另開線程,所以如果是多次,我們需要使用一個線程池來進行管理。
如果需要多次發送數據,可以將其進行封裝成一個函數。

 

接收數據
接收數據實際上是進行 while 循環,循環進行讀取數據,這個最好在連接成功后就開始,比如客戶端:
localSocket.connect(LocalSocketAddress("xxx"))
var runnable = Runnable { 
   while (localSocket.isConnected) {
         var input = localSocket.inputStreaminput.read(data)        
         ...
    }
}
Thread(runnable).start()
接收數據實際上是一個 while 循環不停的進行讀取,未讀到數據就繼續循環,讀到數據就進行處理再循環,所以這里只另開一個線程即可,不需要線程池。
傳輸復雜數據
上面只是簡單事例,無法傳輸復雜數據,如果要傳輸復雜數據,就需要使用 DataInputStreamDataOutputStream

首先需要定義一套協議。

 

比如定義一個簡單的協議: 傳輸的數據分兩部分,第一部分是一個 int 值,表示后面 byte 數據的長度;第二部分就是 byte 數據。這樣就知道如何進行讀寫。

 

寫數據

 
var pool = Executors.newSingleThreadExecutor()
var out = DataOutputStream(xxxSocket.outputStream)
var runnable = Runnable {
        try {
               out.writeInt(data.size) out.write(data) out.flush()
        } catch (e: Throwable) {
               Log.e("xxx", "xxx", e) 
        }
}
pool.execute(runnable)
 

 

讀數據

var runnable = Runnable { 
         var input = DataInputStream(xxxSocket.inputStream) 
         var outArray = ByteArrayOutputStream()
         while (true) {   
                 outArray.reset()
                 var length = input.readInt()
                 if(length > 0) {
                    var buffer = ByteArray(length)
                    input.read(buffer) 
                    ... 
                 }
        }
}
Thread(runnable).start()
這樣就可以傳輸復雜數據,不會導致數據錯亂。

 

傳輸超大數據
上面雖然可以傳輸復雜數據,但是當我們的數據過大的時候,也會出現問題。
比如傳輸圖片或視頻,假設 byte 數據長度達到 1228800,這時我們通過:
var buffer = ByteArray(1228800)
input.read(buffer)
無法讀取到所有數據,只能讀到一部分。而且會造成后面數據的混亂,因為讀取位置錯位了。
讀取的長度大約是 65535 個字節,這是因為 TCP 被 IP 包包著,也會有包大小限制 65535。
但是注意!寫數據的時候如果數據過大就會自動進行分包,但是讀數據的時候如果一次讀取貌似無法跨包,這樣就導致了上面的結果,只能讀一個包,后面的就錯亂了。
那么這種超大數據該如何傳輸呢,我們用循環將其一點點寫入,也一點點讀出,并根據結果不斷的修正偏移。代碼:

 

寫入

var pool = Executors.newSingleThreadExecutor()
var out = DataOutputStream(xxxSocket.outputStream)
var runnable = Runnable {
          try {
              out.writeInt(data.size) 
              var offset = 0 
              while ((offset + 1024) <= data.size) {
                  out.write(data, offset, 1024) 
                  offset += 1024 
              }
              out.write(data, offset, data.size - offset)
              out.flush()
           } catch (e: Throwable) {
              Log.e("xxxx", "xxxx", e)
           }
}
pool.execute(runnable)

 

讀取

var input = DataInputStream(xxxSocket.inputStream)
var runnable = Runnable {
          var outArray = ByteArrayOutputStream()
          while (true) {
                outArray.reset()
                var length = input.readInt()
                if(length > 0) {
                    var buffer = ByteArray(1024)
                    var total = 0 
                    while (total + 1024 <= length) {
                        var count = input.read(buffer)
                        outArray.write(buffer, 0, count)
                        total += count
                    }
                    var buffer2 = ByteArray(length - total)
                    input.read(buffer2)
                    outArray.write(buffer2)
                    var result = outArray.toByteArray()
                    ... 
                }
         }
}
Thread(runnable).start()
 
這樣可以避免因為分包而導致讀取的長度不匹配的問題。
文章來自個人專欄
文章 | 訂閱
0條評論
0 / 1000
請輸入你的評論
0
0