Java WebSocket的使用(有代码案例)

什么是WebSocket

WebSocket是一种在Web开发中用于实现双向双向通信的协议。
它允许在客户端和服务器之间建立持久性的连接,使得数据可以在双方之间进行实时交换,而不需要客户端发起多个HTTP请求

在这里插入图片描述

WebSocket的特点:

  1. 双向通信

webSocke允许客户端和服务器之间双向实时通信,客户端可以向服务器发送消息,服务器也可以向客户端发送消息。

  1. 持久连接

webSocket连接是持久性的,一旦建立连接,他会保持打开状态,直到其中一方主动关闭连接

  1. 低延迟

    webSocket使用单个TCP连接进行通信,相比多次HTTP请求-响应循环,具有更低的通信延迟

  2. 轻量级

    webSocket协议相对简单,通信数据头部较小,减少了通信的额外开销

webSocket和HTTP的区别

  1. 通信模式

HTTP是一种无状态的请求-响应协议,客户端向服务器发送请求,服务器处理请求并返回响应,然后连接立即关闭。每个请求都是独立的,不会保持连接状态
WebSocket允许在客户端和服务器之间建立持久性的双向连接,客户端和服务器可以通过这个连接实时的交换数据。客户端和服务器都可以同时发送和接收数据

  1. 连接性

HTTP协议是基于请求-响应模式的,每次请求都需要客户端发起新的连接,并在收到响应后关闭
WebSocket允许客户端和服务器之间建立持久性连接,连接建立之后可以一直保持打开状态,直到其中一方主动关闭连接或者发生错误

  1. 数据格式

HTTP协议通常用于传输文档、图像、视频等静态资源或者动态资源,数据格式通常是文本或者是二进制,但是在每次请求和响应中都需要携带HTTP的头部信息
webSocket协议支持传输文本或二进制数据,数据格式更加灵活,可以根据应用程序的需要自定义

  1. 性能和效率

HTTP协议在每次请求-响应周期中都需要消耗额外的资源来建立和关闭连接,通信效率相对较低
webSocket通过在客户端和服务器之间建立持久连接,减少建立和关闭的开销,通信效率更高,延迟更低

webSocket的常用常见

在线聊天、股票行情、在线投票和调查,实时地图和位置等

怎么用WebSocket

前端(Vue)

<template>
  <div>
    <el-form ref="form" :model="form" :rules="rules" label-width="80px">
      <el-input v-model="form.message" type="text"></el-input>
      <el-button type="success" @click="send">发送消息</el-button>
      <el-button type="danger" @click="close">关闭连接</el-button>
    </el-form>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  props: {
    msg: String,
  },
  data() {
    return {
      clientId: null,
      form: { message: "" },
      rules: {},
      path: null,
      socket: "",
    };
  },
  mounted() {
    //进行初始化操作
    this.init();
  },
  methods: {
    init() {
      //判断浏览器是否支持webSocket
      if (typeof WebSocket === "undefined") {
        alert("您的浏览器不支持socket");
      } else {
        //clientId是表示哪个客户端
        this.clientId = Math.random().toString(36).substring(2);
        console.log("clientId", this.clientId);
        //初始化webSocket的地址
        this.path = "ws://127.0.0.1:9140/ws/" + this.clientId;
        //创建webSocket对象
        this.socket = new WebSocket(this.path);
        this.socket.onopen = this.open();
        this.socket.onerror = this.error();
        this.socket.onmessage = this.getMessage();
      }
    },

    open() {
      console.log("socket连接成功");
    },
    error() {
      console.log("socket连接错误");
    },
    getMessage() {
      console.log(this.form.message);
    },
    close() {
      console.log("socket已经关闭");
    },
    send() {
      this.socket.send(this.form.message);
    },
  },
  destroyed() {
    //销毁监听
    this.socket.onclose = this.close;
  },
};
</script>
<style scoped>
</style>

后端(Java)

  1. 添加依赖(自己选择版本,我用的版本是这个)
    <!--websocket-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-websocket</artifactId>
      <version>2.1.8.RELEASE</version>
    </dependency>
  1. 创建注册WebSocket的服务组件
/**
 * 注册web Socket的服务组件
 */
@Configuration
public class WebSocketConfiguration {


    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}


  1. 通信服务
/**
 *  导入web Socket服务端组件web Socket Server用于和客户端通信
 */
@Component
@ServerEndpoint("/ws/{clientId}")
public class WebSocketServer {

    private static Map<String, Session> sessionMap = new HashMap<>();


    @OnOpen
    public void opOpen(Session session, @PathParam("clientId") String clientId) {
        System.err.println("客户端:" + clientId + "建立连结");
        sessionMap.put(clientId, session);
    }

    @OnClose
    public void onClose(@PathParam("clientId") String clientId) {
        sessionMap.remove(clientId);
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message  客户端发送过来的消息
     * @param clientId
     */
    @OnMessage
    public void onMessage(String message, @PathParam("clientId") String clientId) {
        System.err.println("收到来自客户端" + clientId + "的消息:" + message);
    }


    public void sendToAllClient(String message) {
        Collection<Session> sessions = sessionMap.values();
        for (Session session : sessions
        ) {
            try {
                session.getBasicRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }


}

  1. 服务端定时发送消息

注意如果用了定时器需要在启动类加上@EnableScheduling注解,否则定时任务不生效

@Component
public class WebSocketTask {

    @Autowired
    private WebSocketServer webSocketServer;


    /**
     * 通过WebSocket每隔5秒向客户端发送消息
     */
    @Scheduled(cron = "0/5 * * * * ?")
    public void sendMessageToClient(){
        System.err.println(LocalDateTime.now());
        webSocketServer.sendToAllClient("这是来自服务端的消息:"+ DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now()));
    }
}
以下是使用 Java WebSocket API 发送字节数组的示例代码: 首先,需要创建一个 WebSocket 客户端类,如下所示: ```java import java.io.IOException; import java.net.URI; import java.nio.ByteBuffer; import java.util.concurrent.CountDownLatch; import javax.websocket.ClientEndpoint; import javax.websocket.CloseReason; import javax.websocket.OnClose; import javax.websocket.OnError; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.WebSocketContainer; @ClientEndpoint public class MyWebSocketClient { private final CountDownLatch latch; private Session session; public MyWebSocketClient(URI endpointURI) { this.latch = new CountDownLatch(1); WebSocketContainer container = javax.websocket.ContainerProvider.getWebSocketContainer(); try { container.connectToServer(this, endpointURI); } catch (Exception e) { throw new RuntimeException(e); } } @OnOpen public void onOpen(Session session) { this.session = session; latch.countDown(); } @OnMessage public void onMessage(String message) { // Handle text message } @OnMessage public void onMessage(ByteBuffer message) { // Handle binary message } @OnError public void onError(Throwable t) { // Handle error } @OnClose public void onClose(CloseReason reason) { // Handle close } public void sendMessage(byte[] data) { if (session != null && session.isOpen()) { ByteBuffer buffer = ByteBuffer.wrap(data); session.getAsyncRemote().sendBinary(buffer); } } public void await() { try { latch.await(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } ``` 然后,可以通过以下代码使用 MyWebSocketClient 类发送字节数组: ```java MyWebSocketClient client = new MyWebSocketClient(new URI("ws://localhost:8080/websocket")); client.await(); byte[] data = // byte array to send client.sendMessage(data); ``` 在 MyWebSocketClient 中,我们实现了 `@OnMessage` 方法来处理二进制消息。我们使用 ByteBuffer 将字节数组包装起来,并使用 `Session.getAsyncRemote().sendBinary()` 方法将其发送到 WebSocket 服务器。 需要注意的是,如果 WebSocket 服务器无法处理二进制消息,将会抛出 `javax.websocket.EncodeException` 异常。在这种情况下,可以尝试使用自定义消息编码器来解决问题。
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值