簡體   English   中英

為什么Android套接字讀取周期性如此緩慢?

[英]Why is Android socket reading so slow periodically?

套接字創建如下:

Socket socket = new Socket();
socket.setReuseAddress(true);
socket.setSoTimeout(iTimeout);
socket.connect(new InetSocketAddress(InetAddress.getByName(uri.getHost()), iPort), 6000);
socket.setReceiveBufferSize(iReceiveBufferSize); //iReceiveBufferSize = 1024*256
final InputStream is = socket.getInputStream();

為了提出這個問題,我們創建並測試了一個調試方法:

public void SocketDebug(InputStream isSocketInput)
{
    try {
        byte[] abBuffer = new byte[1024*256];
        for(int i = 0; i < 1000; i++)
        {
            long lStart = System.currentTimeMillis();
            int iRead = isSocketInput.read(abBuffer, 1024 * 10, 1024 * 128);
            int iElapse = (int)(System.currentTimeMillis() - lStart);
            if(iElapse > 100)
            {
                utility.logd("Debug", "i:" + i + " iElapse:" + iElapse + " iRead:" + iRead);
            }
        }
    }
    catch(Exception ex)
    {

    }
}

以下是logcat記錄的內容的一部分:

01-Jun  37:26.8 i:9     iElapse:234 iRead:1448
01-Jun  37:29.5 i:114   iElapse:299 iRead:1448
01-Jun  37:29.8 i:126   iElapse:298 iRead:1448
01-Jun  37:30.1 i:132   iElapse:300 iRead:1448
01-Jun  37:30.4 i:139   iElapse:283 iRead:1448
01-Jun  37:30.7 i:146   iElapse:287 iRead:1448
01-Jun  37:31.0 i:160   iElapse:269 iRead:1448
01-Jun  37:31.3 i:169   iElapse:251 iRead:44888
01-Jun  37:31.5 i:170   iElapse:192 iRead:1448
01-Jun  37:31.7 i:185   iElapse:170 iRead:1448
01-Jun  37:32.0 i:198   iElapse:171 iRead:1448
01-Jun  37:32.2 i:217   iElapse:158 iRead:1448
01-Jun  37:32.5 i:240   iElapse:162 iRead:1448
01-Jun  37:32.7 i:259   iElapse:135 iRead:1448
01-Jun  37:33.0 i:281   iElapse:103 iRead:1448
01-Jun  37:34.2 i:324   iElapse:826 iRead:1448
01-Jun  37:34.4 i:330   iElapse:233 iRead:1448
01-Jun  37:34.7 i:336   iElapse:264 iRead:1448
01-Jun  37:35.0 i:341   iElapse:299 iRead:1448
01-Jun  37:35.3 i:346   iElapse:300 iRead:1448
01-Jun  37:35.6 i:352   iElapse:297 iRead:1448
01-Jun  37:36.0 i:354   iElapse:317 iRead:21720
01-Jun  37:36.3 i:355   iElapse:304 iRead:13032

數據源是視頻流服務器。 大多數情況下,isSocketInput.read()只需1到3毫秒(上面的日志中沒有顯示)。 但是,周期性地需要100到1000毫秒。 查看紅色字節數,顯然1448是TCP有效負載。 所有紅色字節的數量都是1448的倍數。人們可能認為服務器發送TCP數據包可能需要很長時間。 很難理解的是isSocketInput.read()有時會讀取如此多的數據包(例如31個數據包= 44888個字節)並且需要很長時間才能返回。 它是否應該在有任何數據時盡快返回?

當運行SocketDebug()時,應用程序的所有其他線程基本上都進入休眠狀態(即在包含Thread.sleep()的循環中)。

任何人都可以提供有關長插座讀取時間的可能原因的提示嗎?

更新(2015-06-03):

上述測試是使用帶有單核CPU(Asus MeMO)的Android平板電腦完成的。 當使用具有四核CPU(AGPTek TP714AQ)的低端通用Android平板電腦進行測試時,isSocketInput.read()使用的時間顯着改善。 在前200次迭代之后,長時間過去的次數減少到零。 即使在最初的200次左右的迭代中,也只有少數很長的時間(> 100 ms)。

在這個時候,我認為單核CPU設備的長期過去主要是由答案中提到的“進程或線程被重新調度”引起的 ,這在單核CPU設備上更頻繁地發生。

它無法以比數據到達更快的速度讀取,並且不會比發送數據更快地發生。 不要責怪接收代碼,責怪發件人或網絡。

當您獲得更多字節數時,可能是在您阻塞更長時間之后,並且在您的進程或線程再次重新計划之前到達了更多數據。 您無法從代碼中控制它。

筆記:

  • 您應該連接之前調用setReceiveBufferSize() ,而不是之后調用。 這樣窗口縮放就可以生效了。
  • 如果您沒有指定本地端口,則調用setReuseAddress()是沒有意義的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM