关于websocket服务端的实现网上比较多,比较流行的是spring boot本身的spring-boot-starter-websocket,至于客户端的话,目前流行的是java-websocket框架,这里拿okhttp框架举个例子说说:
1、引入okhttp:
<dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.2.2</version> </dependency>
2、主要实现类继承websocket监听器:
package com.wlf.ws; import com.alibaba.fastjson.JSONObject; import com.wlf.entity.WSResponse; import lombok.extern.slf4j.Slf4j; import okhttp3.Response; import okhttp3.WebSocket; import okhttp3.WebSocketListener; import okio.ByteString; import java.io.IOException; @Slf4j public class SubTitleWS extends WebSocketListener { /** * websocket连接建立后来到这个方法 * * @param webSocket * @param response */ @Override public void onOpen(WebSocket webSocket, Response response) { super.onOpen(webSocket, response); // 打印连接建立后的响应 try { log.info(response.body().string()); } catch (IOException e) { log.error("call onOpen failed, error :{}", e.getMessage()); } } @Override public void onMessage(WebSocket webSocket, String text) { super.onMessage(webSocket, text); log.info("receive=>" + text); //处理返回数据 WSResponse response = (WSResponse) JSONObject.parse(text); if (response != null) { if (!"200".equals(response.getCode())) { log.error("code=> :{}, error=> :{}", response.getCode(), response.getMessage()); return; } } } @Override public void onMessage(WebSocket webSocket, ByteString bytes) { super.onMessage(webSocket, bytes); } @Override public void onClosing(WebSocket webSocket, int code, String reason) { super.onClosing(webSocket, code, reason); log.info("socket closing."); } @Override public void onClosed(WebSocket webSocket, int code, String reason) { super.onClosed(webSocket, code, reason); log.info("socket closed."); } @Override public void onFailure(WebSocket webSocket, Throwable t, Response response) { super.onFailure(webSocket, t, response); if (response == null) { log.error("onFailure, response is null."); return; } try { log.error("onFailure, code: {}, errmsg: {}", response.code(), response.body().string()); } catch (IOException e) { log.warn("onFailure failed, error: {}", e.getMessage()); } } }
3、构造websocket客户端请求:
package com.wlf.service; import com.wlf.utils.MD5Util; import com.wlf.ws.SubTitleWS; import lombok.extern.slf4j.Slf4j; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.WebSocket; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.security.NoSuchAlgorithmException; @Slf4j @Service public class LiveMixService { // websocket客户端对象 final OkHttpClient webSocketClient = new OkHttpClient.Builder().build(); // websocket请求url @Value("${subTitleUrl}") private String subTitleUrl; @Value("${secret}") private String secret; /** * 发起字幕合成 */ public void liveMix(String liveId) throws NoSuchAlgorithmException { sendRequest(liveId); } /** * 发送websocket建立连接请求 * * @param liveId */ private void sendRequest(String liveId) throws NoSuchAlgorithmException { String seed = subTitleUrl + "?liveId=" + liveId + "+" + secret; String md5 = MD5Util.md5Sum(seed); String url = subTitleUrl + "?liveId=" + liveId + "&md5=" + md5; log.info("websocket url: {}", url); // 构造请求对象 Request request = new Request.Builder().url(url).build(); // 调用websocket服务端 WebSocket webSocket = webSocketClient.newWebSocket(request, new SubTitleWS()); } }
完事了,我们启动运行下,看下客户端连接服务端的日志:
2020-04-29 18:14:11 [http-nio-8089-exec-1] INFO com.wlf.service.LiveMixService - websocket url: ws://100.100.10.110:8800/ws/subtitleConnect?liveId=1234&md5=6021b9576f99c883949fb0901a099218 2020-04-29 18:15:12 [OkHttp http://100.100.10.110:8800/...] INFO com.wlf.ws.SubTitleWS - 2020-04-29 18:15:12 [OkHttp http://100.100.10.110:8800/...] INFO com.wlf.ws.SubTitleWS - receive=>{"code":"200","message":"success"} 2020-04-29 18:15:12 [OkHttp http://100.100.10.110:8800/...] ERROR com.wlf.ws.SubTitleWS - onFailure, response is null.
上面的日志发现连接是成功的,服务端在链接建立后返回了200,但随后就抽风挂掉了。