写在前面

最近在写一个web项目,需要实现web客户端之间的语音通话,期望能够借助webSocket全双工通信的方式来实现,但是网上没有发现可以正确使用的代码。网上能找到的一个代码使用之后只能听到“嘀嘀嘀”的杂音

解决方案:使用Json来传递数据代替原有的二进制输入输出流

技术栈:VUE3、SpingBoot、WebSocket

Java后端代码

pom.xml

配置Maven所需的jar包

org.springframework.boot

spring-boot-starter-websocket

WebSocketConfig.java

webSocket配置类

package com.shu.config;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration

public class WebSocketConfig {

/**

* 注入ServerEndpointExporter,

* 这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint

*/

@Bean

public ServerEndpointExporter serverEndpointExporter() {

return new ServerEndpointExporter();

}

}

WebSocketAudioServer.java

webSocket实现类,其中roomId是语音聊天室的id,userId是发送语音的用户id

所以前端请求加入webSocket时候的请求样例应该是:ws://localhost:8080/audio/1/123这个请求中1是roomId,123是userId,这里建议使用ws,一般来说ws对于http,wss对应https

package com.shu.socket;

import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Component;

import jakarta.websocket.OnClose;

import jakarta.websocket.OnError;

import jakarta.websocket.OnMessage;

import jakarta.websocket.OnOpen;

import jakarta.websocket.Session;

import jakarta.websocket.server.PathParam;

import jakarta.websocket.server.ServerEndpoint;

import java.io.BufferedInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.nio.ByteBuffer;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import java.util.concurrent.ConcurrentHashMap;

import java.util.concurrent.CopyOnWriteArraySet;

/**

* @Author:Long

**/

@Component

@Slf4j

@ServerEndpoint(value = "/audio/{roomId}/{userId}")

public class WebSocketAudioServer {

private static ConcurrentHashMap sessionPool = new ConcurrentHashMap();

private static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet<>();

private Session webSocketsession;

private String roomId;

private String userId;

@OnOpen

public void onOpen(@PathParam(value = "roomId") String roomId, @PathParam(value = "userId") String userId,

Session webSocketsession) {

// 接收到发送消息的人员编号

this.roomId = roomId;

this.userId = userId;

// 加入map中,绑定当前用户和socket

sessionPool.put(userId, webSocketsession);

webSocketSet.add(this);

this.webSocketsession = webSocketsession;

// 在线数加1

addOnlineCount();

System.out.println("user编号:" + userId + ":加入Room:" + roomId + "语音聊天 " + "总数为:" + webSocketSet.size());

}

@OnClose

public void onClose() {

try {

sessionPool.remove(this.userId);

} catch (Exception e) {

}

}

@OnMessage(maxMessageSize = 5242880)

public void onMessage(@PathParam(value = "roomId") String roomId, @PathParam(value = "userId") String userId,

String inputStream) {

try {

for (WebSocketAudioServer webSocket : webSocketSet) {

try {

if (webSocket.webSocketsession.isOpen() && webSocket.roomId.equals(roomId)

&& !webSocket.userId.equals(userId)) {

webSocket.webSocketsession.getBasicRemote().sendText(inputStream);

}

} catch (Exception e) {

e.printStackTrace();

}

}

} catch (Exception e) {

e.printStackTrace();

}

}

@OnError

public void onError(Session session, Throwable error) {

error.printStackTrace();

}

/**

* 为指定用户发送消息

*

*/

public void sendMessage(String message) throws IOException {

// 加同步锁,解决多线程下发送消息异常关闭

synchronized (this.webSocketsession) {

this.webSocketsession.getBasicRemote().sendText(message);

}

}

public List getOnlineUser(String roomId) {

List userList = new ArrayList();

for (WebSocketAudioServer webSocketAudioServer : webSocketSet) {

try {

if (webSocketAudioServer.webSocketsession.isOpen() && webSocketAudioServer.roomId.equals(roomId)) {

if (!userList.contains(webSocketAudioServer.userId)) {

userList.add(webSocketAudioServer.userId);

}

}

} catch (Exception e) {

e.printStackTrace();

}

}

return userList;

}

}

VUE前端代码

audioChat.vue

这段代码是博主从自己的vue代码中截取出来的(原本的代码太多了),可能有些部分代码有函数没写上(如果有错的话麻烦大家在评论区指出,博主会及时修改)

注意事项

之前有博客使用二进制数据输入输出流来向后端传输数据,但是功能无法实现,后来发现那位博主的数据并没有发成功,我直接在Java中使用Json来传输float数组数据,实现了语音通话功能。

关于Chrome或Edge浏览器报错

关于谷歌浏览器提示TypeError: Cannot read property ‘getUserMedia’ of undefined

解决方案: 1.网页使用https访问,服务端升级为https访问,配置ssl证书 2.使用localhost或127.0.0.1 进行访问 3.修改浏览器安全配置

在chrome浏览器中输入如下指令

chrome://flags/#unsafely-treat-insecure-origin-as-secure

开启 Insecure origins treated as secure 在下方输入栏内输入你访问的地址url,然后将右侧Disabled 改成 Enabled即可

浏览器会提示重启, 点击Relaunch即可

好文阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: