您好,登錄后才能下訂單哦!
websocket 和傳統意義上的socket編程雖然存在差別,但也存在相通概念,也分服務端和客戶端。
主要區別
對于websocket,客戶端的編寫方式是通過JS編寫回調函數完成交互;而傳統socket,則需要連接端口,通過輸入輸出流來傳遞信息,完成交互;
傳統的socket,服務端則需要綁定端口,通過accept 方法,等待客戶端的連接。websocket 規范則把處理細節由web服務器來完成。
數據處理是websocket的一項主要工作。按工作階段劃分,主要包括以下方面。
信息發送
信息解碼
信息編碼
信息接收
按傳遞數據劃分,分為
文本信息
二進制流信息
ping/pong信息
上面的內容,僅限于服務端,websocket html5相關暫時不討論
1.信息發送( Sending Messages)
表示服務端,將消息傳遞給客戶端(peer)
1.1將消息廣播到所有連接客戶端
@ServerEndpoint("/echoall") public class EchoAllEndpoint { @OnMessage public void onMessage(Session session, String msg) {//1 try { for (Session sess : session.getOpenSessions()) { if (sess.isOpen()) sess.getBasicRemote().sendText(msg);//2,3 } } catch (IOException e) { ... } } }
信息發送三步
1.Obtain the Session
object from the connection.(通過在參數中添加Session,獲取Session)
2.Use the Session
object to obtain a RemoteEndpoint
object.
3.Use the RemoteEndpoint
object to send messages to the peer.
1.2返回值,作為信息發送
@OnMessage public String onMessage(String message,Session session) { System.out.println("Received : "+ message); return message+"-"+session.getId(); }
2.信息解碼和編碼(codec)
拿打電話為例,如果電話雙方,都用一樣的標準普通話溝通,就沒必要用翻譯器了。如果電話雙方,一邊用著標準的牛津話,一方操著標準的山東土話,想想也能想想出來,溝通直接亂掉了,這時候必須要用到雙方必須都需要翻譯器了。websocket的編碼和解碼部分就是“翻譯器”的角色。
編碼及×××位置
可以簡單理解為:解碼就是反序列化的過程;編碼就是序列化的過程。
2.1 使用Encoders 反序列化對象
響應信息需要轉換成二進制,才能進行網絡傳遞。
來自j2ee的例子
1.實現Encoder.Text<T> 或Encoder.Binary<T>接口
public class MessageATextEncoder implements Encoder.Text<MessageA> { @Override public void init(EndpointConfig ec) { } @Override public void destroy() { } @Override public String encode(MessageA msgA) throws EncodeException { // Access msgA's properties and convert to JSON text... return msgAJsonString; } }
2.將第一步中新建的Encoder,添加到ServerEndpoint 注解的encoders 屬性中
@ServerEndpoint( value = "/myendpoint", encoders = { MessageATextEncoder.class, MessageBTextEncoder.class } ) public class EncEndpoint { ... }
3.使用RemoteEndpoint.Basic or RemoteEndpoint.Async 的sendObject發送對象。
MessageA msgA = new MessageA(...); MessageB msgB = new MessageB(...); session.getBasicRemote.sendObject(msgA); session.getBasicRemote.sendObject(msgB);
2.2 使用Decoders 序列化信息
將請求信息轉換成對象,才方便ServerPoint處理響應
與Encoders處理步驟類似
1.實現Decoder.Text<T>或Decoder.Binary
<T>接口
public class MessageTextDecoder implements Decoder.Text<Message> { @Override public void init(EndpointConfig ec) { } @Override public void destroy() { } @Override public Message decode(String string) throws DecodeException { // Read message... if ( /* message is an A message */ ) return new MessageA(...); else if ( /* message is a B message */ ) return new MessageB(...); } @Override public boolean willDecode(String string) { // Determine if the message can be converted into either a // MessageA object or a MessageB object... return canDecode; } }
請注意willDecode方法,決定是否進行解碼
2. 新建的Decoder,添加到ServerEndpoint 注解的decoders 屬性中
@ServerEndpoint( value = "/myendpoint", encoders = { MessageATextEncoder.class, MessageBTextEncoder.class }, decoders = { MessageTextDecoder.class } ) public class EncDecEndpoint { ... }
3. 這時候就可以在@OnMessage注解的參數方法中直接使用Decoder.decode返回的對象類型了。
@OnMessage public void message(Session session, Message msg) { if (msg instanceof MessageA) { // We received a MessageA object... } else if (msg instanceof MessageB) { // We received a MessageB object... } }
具體例子,見我的github項目。https://github.com/janecms/websocket_example
(XML)編碼解密處理(codec)
(JSON)編碼解密處理(codec)
3.信息接收(Receiving Messages)
3.1 接收三種不同形式消息
package com.sample.websocket.endpoint; import javax.websocket.OnMessage; import javax.websocket.PongMessage; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; import java.nio.ByteBuffer; @ServerEndpoint("/receive") public class ReceiveEndpoint { @OnMessage public void textMessage(Session session, String msg) { System.out.println("Text message: " + msg); } @OnMessage public void textMessage(Session session, String msg) { System.out.println("Text message: " + msg); } @OnMessage public void binaryMessage(Session session, ByteBuffer msg) { System.out.println("Binary message: " + msg.toString()); } @OnMessage public void pongMessage(Session session, PongMessage msg) { System.out.println("Pong message: " + msg.getApplicationData().toString()); } }
一個奇怪的情況,不同版本的Tomcat,對@OnMessage注解的方法限制有所不同。也進一步說明,websocket規范是個快速變化中的規范。有的直接編譯期出錯;有的運行時錯誤。(有可能和我選擇不同版本的開發工具有關系,不太確定,一樣的代碼,表現不同的行為,蹊蹺)
需要注意的是被OnMessage注解的三個方法,分別接收不同的消息類型。
3.2 錯誤代碼
@ServerEndpoint("/echo") public class EchoEndpoint { @OnMessage public String onMessage(String message,Session session) { System.out.println("Received : "+ message); return message+"-"+session.getId(); } @OnMessage public String onMessage2(String message,Session session) { System.out.println("Received : "+ message); return message+"####"+session.getId(); } }
代碼,報運行時異常。
javax.servlet.ServletException: javax.websocket.DeploymentException: Duplicate annotation
一種消息類型,只能對應一個OnMessage方法。
參考資源
https://docs.oracle.com/javaee/7/tutorial/websocket005.htm
結論:主要討論了消息相關的內容 按消息處理的不同階段進行總結。接下來即將討論websocket相關的配置信息,及錯誤處理。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。