天天看點

WebSocket是一種協定

        WebSocket,并非HTML 5獨有,WebSocket是一種協定。隻是在handshake的時候,發送的連結資訊頭和HTTP相似。HTML 5隻是實作了WebSocket的用戶端。其實,難點在于服務端,服務端相對還是比較複雜的。

WebSocket是一種協定
WebSocket是一種協定

        也就說,你需要解讀opcode, Payload len 這些比較敏感的位值之後,你才開始取後面的Payload Data, 比如opcode如果是1,那麼就是讀取字元串,如果是2,那麼就是讀取流。

        如果自己用java做服務端,握手協定的響應,換行符不能使“\r\n”或“\n”,因為這不是标準的換行符,其實是個字元串,隻是螢幕顯示的時候是換行,可以用PrintWrite.println(),或者

String newLine = (String) java.security.AccessController.doPrivileged(

              new sun.security.action.GetPropertyAction("line.separator"));

        握手之後,根據opcode做相應的操作,JAVA的IO和NIO,在實作方面都缺憾,難以實作。使用IO的話,在獲得socket之 後,InputStream會處于阻塞,因為阻塞,是以後續做outputStream的操作時就會不友善。NIO的話,是SocketChannel寫 入讀出,基本都是ByteBuffer,用這個的話,有時opcode值為1(讀取字元串),ByteBuffer解碼得到的字元串經常性是亂碼。感覺最 好還是學Tomcat,自己重寫一下InputStream。

    Tomcat在7.0.27之後就開始支援WebSocket,在它之上建立WebSocket是很簡單的,基本就是繼承 WebSocketServlet,實作createWebSocketInbound方法和重寫StreamInbound的方法。Tomcat的 example裡面有相關的例子。

    Tomcat處理流程,WebSocketServlet本身就繼承了HttpServlet,重寫doGet方法,在doGet方法裡面做了 handshake的操作,之後就是一些UpgradeInbound的操作,做好接收資料流的準備(StreamInbound提供了onData方 法)。每次資料過來,都會執行onData裡面的WsFrame frame = wsIs.nextFrame(true); 對資料幀進行分析,并且提供自定義InputStream流,調用使用者重寫的onBinaryData或者onTextData方法,将輸入流裡面的資料 讀出,再response給用戶端。

 WebSocketServlet(doGet) -> handshake ->  createWebSocketInbound  ->  doUpgrade  -> setUpgradeProcessor -> 

onUpgradeComplete  -> onData -> 資料過來 -> wsIs.nextFrame(true)  ->  生成自定義InputStream -> 調用使用者重寫方法  (另外如果opcode是關閉Socket,也會有相應的操作)

http://www.open-open.com/lib/view/open1344582940452.html