
# 应用示例
#### 应用场景
本小节介绍WebSocket建链、信息订阅、信息推送以及心跳保持的调用顺序。
#### 业务流程
WebSocket建链、订阅、信息推送的流程图如下：
图1Websocket消息推送流程图   
![](https://support.huaweicloud.com/api-meeting/figure/zh-cn_image_0000001124450257.png)
1. 根据会议ID及主持人密码获取会控Token和建链Websocket所需的服务端地址。请参考"[获取会控Token - CreateConfToken](https://support.huaweicloud.com/api-meeting/meeting_21_0027.html)"接口。
2. 使用会控Token获取Websocket建链Token。请参考"[获取WebSocket建链Token - CreateWebSocketToken](https://support.huaweicloud.com/api-meeting/meeting_21_1506.html)"接口。
3. 与服务端建立Websocket链接。
4. 订阅需要华为云会议服务端推送的信息类型。
5. 华为云会议服务端推送订阅的信息。
6. 至少在180秒内发送一次心跳消息。
#### 代码示例1：
前端WebSocket建链、订阅，收发消息代码。
```
<!DOCTYPE HTML>
<html>
   <head>
   <meta charset="utf-8">
   <title>WebSocket建链和消息收发</title>
      <script type="text/javascript">
         function WebSocketTest()
         {
            if ("WebSocket" in window)
            {
               // webSocket建链
var confID = "900964776";
var tempToken = "&tmpToken=" + "获取WebSocket建链Token";
var uri = "wss://100.94.23.40:443/cms/open/websocket/confctl/increment/conn?confID=" + confID + tempToken;
               var ws = new WebSocket(uri);
               ws.onopen = function()
               {
                // WebSocket已连接，发送订阅消息
var senddata = JSON.stringify({
sequence: "000000000000000002611382273415",
action: "Subscribe",
data: JSON.stringify({
subscribeType: [
"ConfBasicInfoNotify",
"ConfDynamicInfoNotify",
"ParticipantsNotify",
"AttendeesNotify",
"SpeakerChangeNotify",
"CustomMultiPicNotify",
"InviteResultNotify",
"InterpreterGroupNotify",
"NetworkQualityNotify"
],
confToken: "获取会控Token",
}),
  });
                  ws.send(senddata);
                  alert("订阅数据发送中：" + senddata);
               };
               ws.onmessage = function (evt) 
               { 
                  var received_msg = evt.data;
                  // alert("数据已接收：" + received_msg);
                };                          
            }
            else
            {
               // 浏览器不支持 WebSocket
               alert("您的浏览器不支持 WebSocket!");
            }
         }
      </script>
   </head>
   <body>
      <div id="meeting">
         <a href="javascript:WebSocketTest()">开始WebSocket建链和订阅</a>
      </div>
   </body>
</html>
```
#### 代码示例2：
Java WebSocket客户端建链、收发消息代码。
```
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
 
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
 
import org.java_websocket.WebSocket;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
 
import com.google.gson.Gson;
 
public class WebSocketClientDemo extends WebSocketClient{
 
    public WebSocketClientDemo(String url) throws URISyntaxException {
        super(new URI(url));
    }
 
    @Override
    public void onOpen(ServerHandshake shake) {
        System.out.println("Hand shake!");
        for(Iterator<String> it = shake.iterateHttpFields(); it.hasNext();) {
            String key = it.next();
            System.out.println(key + ":" + shake.getFieldValue(key));
        }
    }
 
    @Override
    public void onMessage(String paramString) {
        System.out.println("receive msg: " + paramString);
    }
 
    @Override
    public void onClose(int paramInt, String paramString, Boolean paramBoolean) {
        System.out.println("Channel close!");
    }
 
    @Override
    public void onError(Exception e) {
        System.out.println("error: " + e);
    }
 
    public static void main(String[] args) throws Exception{
        try {
            // webSocket建链
            String confID = "900964776";
            String tempToken = "&tmpToken=" + "获取WebSocket建链Token";
            String url = "wss://100.94.23.40:443/cms/open/websocket/confctl/increment/conn?confID=" + confID
                    + tempToken;
            WebSocketClientDemo client = new WebSocketClientDemo(url);
            client.connect();
 
            while (!client.getReadyState().equals(WebSocket.READYSTATE.OPEN)) {
                System.out.println("Not open yet");
                Thread.sleep(100);
            }
 
            System.out.println("WebSocket channel connected!");
            // WebSocket已连接，发送订阅消息
            Gson gson = new Gson();
 
            List<SubscribeType> subscribeTypes = new ArrayList<>();
            subscribeTypes.add(SubscribeType.ConfBasicInfoNotify);
            subscribeTypes.add(SubscribeType.ConfDynamicInfoNotify);
            subscribeTypes.add(SubscribeType.ParticipantsNotify);
            subscribeTypes.add(SubscribeType.AttendeesNotify);
            subscribeTypes.add(SubscribeType.SpeakerChangeNotify);
            subscribeTypes.add(SubscribeType.InviteResultNotify);
 
            SubscribeReq subscribeReq = SubscribeReq.builder()
                    .subscribeType(subscribeTypes)
                    .confToken(获取会控Token)
                    .build();
            SubscribeMsgFrame subscribeMsgFrame = SubscribeMsgFrame.builder()
                    .action("Subscribe")
                    .sequence("000000000000000002611382271289")
                    .data(gson.toJson(subscribeReq))
                    .build();
 
            String jsonStr = gson.toJson(subscribeMsgFrame);
            client.send(jsonStr);
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }
}
Java WebSocket客户端建链收发消息。
SubscribeReq.java
------
import java.util.List;
 
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
 
@Getter
@Setter
@Builder
public class SubscribeReq {
 
    /**
     * 订阅类型
     */
    List<SubscribeType> subscribeType;
 
    /**
     * 会议Token
     */
    String confToken;
}
SubscribeMsgFrame .java
------
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
 
@Getter
@Setter
@Builder
public class SubscribeMsgFrame {
 
    /**
     * 消息类型
     */
    String action;
 
    /**
     * 消息随机序列号
     */
    String sequence;
 
    /**
     * 消息体
     */
    String data;
}
```
