1. 程式人生 > >WebSocket的ping與pong的java實現…

WebSocket的ping與pong的java實現…

  網上大多數例子給的都是echo server,也就是當websocket客戶端連結進來以後,客戶端發一條訊息,伺服器就把這條訊息原班不動地返回去。而且絕大多數沒有進行ping、pong判斷。於是就出現一個問題:當電腦瀏覽器傳送pong幀的時候,由於內容為空,於是伺服器將空內容轉發回去,導致客戶端瀏覽器以為是錯誤的幀型別,傳送關閉資訊進行error關閉。   一開始還誤以為是瀏覽器傳送ping幀,伺服器沒有回覆pong幀導致的,最後用wireshark抓包解析才發現瀏覽器傳送的是pong幀……居然有單獨傳送pong幀,給跪了,還以為一ping一pong很合拍呢。網上的資料也證實了這個說法,javascript中並沒有傳送ping和pong的API,全靠瀏覽器自己的行為:  “我這隻有個go的例子 https:// github.com /gorilla /websocket /blob /master /examples /chat /conn.go 只能server端主動去ping,客戶端pong,反之不行,看起來似乎只能起個心跳的作用   “……There is no Javascript API to send ping frames or receive pong frames. This is either supported by your browser, or not. There is also no API to enable, configure or detect whether the browser supports and is using ping/pong frames.……
  於是,實際測試中,IE11會在雙方都不收發訊息的情況下每隔30秒發一個pong幀,iOS 7上的safari和Android 5.0自帶瀏覽器則不會發送任何pong幀。   所以,如何解決瀏覽器一pong就關閉連結的問題呢?   答案就是啥也不做。之前正是因為返回空幀給瀏覽器,所以才導致了瀏覽器斷開連結。 如果你一定一定要傳送個ping幀回覆下,那麼: ___________________________________________________________________________________________ public void sendPingFrame() throws IOException, SocketException{         byte[] abcde=new byte[2];         abcde[0]=(byte) 0x89;    //1000 1001 fin設定為true,OpCode是9
        abcde[1]=(byte) 0x00;    //0000 0000 沒有掩碼,幀長度設定為0         outData.write(abcde);    //outData是DataOutputStream型別 } ___________________________________________________________________________________________   自然,在接收WebSocket客戶端發來的幀頭的時候,也要拆開的判斷OpCode操作碼: ___________________________________________________________________________________________ if(dr.getOpCode()==0xa){ onPong(); }else if(dr.getOpCode()==0x8){ onClose(); }else{ onReceive(analyRcvData); } ___________________________________________________________________________________________ 最後附上把byte轉換為10101010等二進位制表示形式String的程式碼: ___________________________________________________________________________________________ private String bitsBuilder2(byte dd){         StringBuilder sb=new StringBuilder();         if((dd & 0x80) == 0x80){             sb.append("1");         }else{             sb.append("0");         }         if((dd & 0x40) == 0x40){             sb.append("1");         }else{             sb.append("0");         }         if((dd & 0x20) == 0x20){             sb.append("1");         }else{             sb.append("0");         }         if((dd & 0x10) == 0x10){             sb.append("1");         }else{             sb.append("0");         }         if((dd & 0x08) == 0x08){             sb.append("1");         }else{             sb.append("0");         }         if((dd & 0x04) == 0x04){             sb.append("1");         }else{             sb.append("0");         }         if((dd & 0x02) == 0x02){             sb.append("1");         }else{             sb.append("0");         }         if((dd & 0x01) == 0x01){             sb.append("1");         }else{             sb.append("0");         }         return sb.toString();     } ___________________________________________________________________________________________